@enrichlayer/el-linear 1.5.0 → 1.7.0
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/README.md +32 -4
- package/dist/auth/oauth-app-config.d.ts +21 -0
- package/dist/auth/oauth-app-config.js +82 -0
- package/dist/commands/attachments.js +11 -12
- package/dist/commands/batch.js +15 -14
- package/dist/commands/comments.js +22 -10
- package/dist/commands/cycles.js +5 -4
- package/dist/commands/documents.js +18 -15
- package/dist/commands/embeds.js +4 -6
- package/dist/commands/graphql.js +5 -4
- package/dist/commands/init/aliases.js +0 -14
- package/dist/commands/init/defaults.d.ts +18 -1
- package/dist/commands/init/defaults.js +83 -8
- package/dist/commands/init/index.js +7 -13
- package/dist/commands/init/oauth.d.ts +4 -4
- package/dist/commands/init/oauth.js +24 -6
- package/dist/commands/init/shared.js +0 -1
- package/dist/commands/init/token.js +0 -7
- package/dist/commands/init/workspace.js +0 -2
- package/dist/commands/issue-id.js +3 -1
- package/dist/commands/issues.js +130 -54
- package/dist/commands/labels.js +23 -9
- package/dist/commands/profile/migrate-legacy.js +0 -1
- package/dist/commands/project-milestones.js +13 -12
- package/dist/commands/projects.js +28 -15
- package/dist/commands/read-shortcut.js +8 -7
- package/dist/commands/refs.js +4 -3
- package/dist/commands/releases.js +9 -8
- package/dist/commands/search.js +3 -2
- package/dist/commands/teams.js +14 -3
- package/dist/commands/templates.js +5 -4
- package/dist/commands/users.js +3 -2
- package/dist/config/config.d.ts +37 -0
- package/dist/config/issue-validation.js +1 -1
- package/dist/config/paths.d.ts +1 -0
- package/dist/config/paths.js +1 -0
- package/dist/config/resolver.js +1 -1
- package/dist/main.js +3 -2
- package/dist/utils/disk-cache.d.ts +51 -0
- package/dist/utils/disk-cache.js +178 -0
- package/dist/utils/download-uploads.d.ts +2 -1
- package/dist/utils/download-uploads.js +2 -4
- package/dist/utils/file-service.d.ts +26 -2
- package/dist/utils/file-service.js +27 -5
- package/dist/utils/footer.d.ts +19 -0
- package/dist/utils/footer.js +27 -0
- package/dist/utils/gdoc-parser.js +1 -1
- package/dist/utils/graphql-attachments-service.d.ts +1 -1
- package/dist/utils/graphql-attachments-service.js +2 -2
- package/dist/utils/graphql-documents-service.d.ts +1 -1
- package/dist/utils/graphql-documents-service.js +2 -2
- package/dist/utils/graphql-service.d.ts +2 -2
- package/dist/utils/graphql-service.js +7 -4
- package/dist/utils/linear-service.d.ts +18 -3
- package/dist/utils/linear-service.js +21 -6
- package/dist/utils/markdown-prosemirror.js +16 -9
- package/dist/utils/root-opts.d.ts +11 -0
- package/dist/utils/root-opts.js +13 -0
- package/dist/utils/validators.d.ts +7 -0
- package/dist/utils/validators.js +14 -14
- package/package.json +1 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Append a footer to a body string.
|
|
3
|
+
*
|
|
4
|
+
* Resolution order:
|
|
5
|
+
* 1. `--no-footer` flag → return body unchanged
|
|
6
|
+
* 2. `--footer <text>` flag → use the explicit value
|
|
7
|
+
* 3. `config.messageFooter` → use the configured value
|
|
8
|
+
* 4. nothing set → return body unchanged
|
|
9
|
+
*
|
|
10
|
+
* The footer is treated as a literal string — callers who want a horizontal
|
|
11
|
+
* rule or blank line before it must include the separator in the value.
|
|
12
|
+
*
|
|
13
|
+
* Used on `create` paths only (issues create, comments create). Update paths
|
|
14
|
+
* take an explicit body the user has already authored, so we don't auto-inject.
|
|
15
|
+
*/
|
|
16
|
+
export declare function applyFooter(body: string | undefined, options: {
|
|
17
|
+
footer?: string;
|
|
18
|
+
noFooter?: boolean;
|
|
19
|
+
}): string | undefined;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { loadConfig } from "../config/config.js";
|
|
2
|
+
/**
|
|
3
|
+
* Append a footer to a body string.
|
|
4
|
+
*
|
|
5
|
+
* Resolution order:
|
|
6
|
+
* 1. `--no-footer` flag → return body unchanged
|
|
7
|
+
* 2. `--footer <text>` flag → use the explicit value
|
|
8
|
+
* 3. `config.messageFooter` → use the configured value
|
|
9
|
+
* 4. nothing set → return body unchanged
|
|
10
|
+
*
|
|
11
|
+
* The footer is treated as a literal string — callers who want a horizontal
|
|
12
|
+
* rule or blank line before it must include the separator in the value.
|
|
13
|
+
*
|
|
14
|
+
* Used on `create` paths only (issues create, comments create). Update paths
|
|
15
|
+
* take an explicit body the user has already authored, so we don't auto-inject.
|
|
16
|
+
*/
|
|
17
|
+
export function applyFooter(body, options) {
|
|
18
|
+
if (options.noFooter) {
|
|
19
|
+
return body;
|
|
20
|
+
}
|
|
21
|
+
const explicit = options.footer;
|
|
22
|
+
const footer = explicit ?? loadConfig().messageFooter;
|
|
23
|
+
if (!footer) {
|
|
24
|
+
return body;
|
|
25
|
+
}
|
|
26
|
+
return body ? `${body}${footer}` : footer;
|
|
27
|
+
}
|
|
@@ -82,7 +82,7 @@ export function parseGoogleDoc(doc) {
|
|
|
82
82
|
.filter((c) => c.paragraph)
|
|
83
83
|
.map((c) => {
|
|
84
84
|
let text = "";
|
|
85
|
-
for (const el of c.paragraph
|
|
85
|
+
for (const el of c.paragraph?.elements ?? []) {
|
|
86
86
|
text += formatTextRun(el);
|
|
87
87
|
}
|
|
88
88
|
return text.replace(TRAILING_NEWLINE_RE, "");
|
|
@@ -8,5 +8,5 @@ declare class GraphQLAttachmentsService {
|
|
|
8
8
|
deleteAttachment(id: string): Promise<boolean>;
|
|
9
9
|
listAttachments(issueId: string): Promise<LinearAttachment[]>;
|
|
10
10
|
}
|
|
11
|
-
export declare function createGraphQLAttachmentsService(options: AuthOptions): GraphQLAttachmentsService
|
|
11
|
+
export declare function createGraphQLAttachmentsService(options: AuthOptions): Promise<GraphQLAttachmentsService>;
|
|
12
12
|
export {};
|
|
@@ -40,7 +40,7 @@ class GraphQLAttachmentsService {
|
|
|
40
40
|
return attachments.nodes.map(transformAttachment);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
export function createGraphQLAttachmentsService(options) {
|
|
44
|
-
const graphqlService = createGraphQLService(options);
|
|
43
|
+
export async function createGraphQLAttachmentsService(options) {
|
|
44
|
+
const graphqlService = await createGraphQLService(options);
|
|
45
45
|
return new GraphQLAttachmentsService(graphqlService);
|
|
46
46
|
}
|
|
@@ -14,5 +14,5 @@ declare class GraphQLDocumentsService {
|
|
|
14
14
|
deleteDocument(id: string): Promise<boolean>;
|
|
15
15
|
listDocumentsBySlugIds(slugIds: string[], limit?: number): Promise<LinearDocument[]>;
|
|
16
16
|
}
|
|
17
|
-
export declare function createGraphQLDocumentsService(options: AuthOptions): GraphQLDocumentsService
|
|
17
|
+
export declare function createGraphQLDocumentsService(options: AuthOptions): Promise<GraphQLDocumentsService>;
|
|
18
18
|
export {};
|
|
@@ -91,7 +91,7 @@ class GraphQLDocumentsService {
|
|
|
91
91
|
return result.documents.nodes.map(transformDocument);
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
|
-
export function createGraphQLDocumentsService(options) {
|
|
95
|
-
const graphqlService = createGraphQLService(options);
|
|
94
|
+
export async function createGraphQLDocumentsService(options) {
|
|
95
|
+
const graphqlService = await createGraphQLService(options);
|
|
96
96
|
return new GraphQLDocumentsService(graphqlService);
|
|
97
97
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { GraphQLResponseData, GraphQLVariables } from "../types/linear.js";
|
|
2
|
-
import {
|
|
2
|
+
import type { AuthOptions } from "./auth.js";
|
|
3
3
|
/**
|
|
4
4
|
* Constructor arg shapes for `GraphQLService`. Three variants:
|
|
5
5
|
* - `string` → personal API token (legacy; sent without `Bearer` prefix).
|
|
@@ -20,4 +20,4 @@ export declare class GraphQLService {
|
|
|
20
20
|
constructor(auth: GraphQLServiceAuth);
|
|
21
21
|
rawRequest<T = GraphQLResponseData>(query: string, variables?: GraphQLVariables): Promise<T>;
|
|
22
22
|
}
|
|
23
|
-
export declare function createGraphQLService(options: AuthOptions): GraphQLService
|
|
23
|
+
export declare function createGraphQLService(options: AuthOptions): Promise<GraphQLService>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LinearClient } from "@linear/sdk";
|
|
2
|
-
import {
|
|
2
|
+
import { getActiveAuth } from "../auth/token-resolver.js";
|
|
3
3
|
function buildLinearClient(auth) {
|
|
4
4
|
const baseHeaders = { "public-file-urls-expire-in": "3600" };
|
|
5
5
|
if (typeof auth === "string") {
|
|
@@ -41,7 +41,10 @@ export class GraphQLService {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
-
export function createGraphQLService(options) {
|
|
45
|
-
const
|
|
46
|
-
|
|
44
|
+
export async function createGraphQLService(options) {
|
|
45
|
+
const auth = await getActiveAuth(options);
|
|
46
|
+
if (auth.kind === "oauth") {
|
|
47
|
+
return new GraphQLService({ oauthToken: auth.token });
|
|
48
|
+
}
|
|
49
|
+
return new GraphQLService({ apiKey: auth.token });
|
|
47
50
|
}
|
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
import type { LinearComment, LinearCycleDetail, LinearCycleSummary, LinearLabel, LinearProject, LinearTeam, LinearUser } from "../types/linear.js";
|
|
2
|
-
import {
|
|
2
|
+
import type { AuthOptions } from "./auth.js";
|
|
3
|
+
/**
|
|
4
|
+
* Constructor arg shapes for `LinearService`. Three variants:
|
|
5
|
+
* - `string` → personal API token (legacy; sent without `Bearer` prefix).
|
|
6
|
+
* - `{apiKey: string}` → personal API token (explicit).
|
|
7
|
+
* - `{oauthToken: string}` → OAuth access token (sent as
|
|
8
|
+
* `Authorization: Bearer <token>` via the SDK's accessToken option).
|
|
9
|
+
*
|
|
10
|
+
* The string variant exists because hundreds of call sites and tests pass
|
|
11
|
+
* a plain string. We continue to support it indefinitely.
|
|
12
|
+
*/
|
|
13
|
+
export type LinearServiceAuth = string | {
|
|
14
|
+
apiKey: string;
|
|
15
|
+
} | {
|
|
16
|
+
oauthToken: string;
|
|
17
|
+
};
|
|
3
18
|
export declare class LinearService {
|
|
4
19
|
private readonly client;
|
|
5
|
-
constructor(
|
|
20
|
+
constructor(auth: LinearServiceAuth);
|
|
6
21
|
resolveIssueId(issueId: string): Promise<string>;
|
|
7
22
|
getTeams(limit?: number): Promise<LinearTeam[]>;
|
|
8
23
|
resolveUserId(nameOrEmailOrId: string): Promise<string>;
|
|
@@ -23,4 +38,4 @@ export declare class LinearService {
|
|
|
23
38
|
resolveCycleId(cycleNameOrId: string, teamFilter?: string): Promise<string>;
|
|
24
39
|
resolveProjectId(projectNameOrId: string): Promise<string>;
|
|
25
40
|
}
|
|
26
|
-
export declare function createLinearService(options: AuthOptions): LinearService
|
|
41
|
+
export declare function createLinearService(options: AuthOptions): Promise<LinearService>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LinearClient } from "@linear/sdk";
|
|
2
|
+
import { getActiveAuth } from "../auth/token-resolver.js";
|
|
2
3
|
import { resolveUserDisplayName } from "../config/resolver.js";
|
|
3
|
-
import { getApiToken } from "./auth.js";
|
|
4
4
|
import { toISOStringOrNow, toISOStringOrUndefined } from "./date-format.js";
|
|
5
5
|
import { multipleMatchesError, notFoundError } from "./error-messages.js";
|
|
6
6
|
import { parseIssueIdentifier } from "./identifier-parser.js";
|
|
@@ -21,10 +21,22 @@ function teamIdFilter(teamId) {
|
|
|
21
21
|
function nonEmptyFilter(filter) {
|
|
22
22
|
return Object.keys(filter).length > 0 ? filter : undefined;
|
|
23
23
|
}
|
|
24
|
+
function buildLinearClient(auth) {
|
|
25
|
+
if (typeof auth === "string") {
|
|
26
|
+
return new LinearClient({ apiKey: auth });
|
|
27
|
+
}
|
|
28
|
+
if ("oauthToken" in auth) {
|
|
29
|
+
// Linear's SDK natively supports OAuth via the `accessToken` option,
|
|
30
|
+
// which causes the underlying transport to send
|
|
31
|
+
// `Authorization: Bearer <token>` instead of the personal-token shape.
|
|
32
|
+
return new LinearClient({ accessToken: auth.oauthToken });
|
|
33
|
+
}
|
|
34
|
+
return new LinearClient({ apiKey: auth.apiKey });
|
|
35
|
+
}
|
|
24
36
|
export class LinearService {
|
|
25
37
|
client;
|
|
26
|
-
constructor(
|
|
27
|
-
this.client =
|
|
38
|
+
constructor(auth) {
|
|
39
|
+
this.client = buildLinearClient(auth);
|
|
28
40
|
}
|
|
29
41
|
async resolveIssueId(issueId) {
|
|
30
42
|
if (isUuid(issueId)) {
|
|
@@ -436,7 +448,10 @@ export class LinearService {
|
|
|
436
448
|
return projectsConnection.nodes[0].id;
|
|
437
449
|
}
|
|
438
450
|
}
|
|
439
|
-
export function createLinearService(options) {
|
|
440
|
-
const
|
|
441
|
-
|
|
451
|
+
export async function createLinearService(options) {
|
|
452
|
+
const auth = await getActiveAuth(options);
|
|
453
|
+
if (auth.kind === "oauth") {
|
|
454
|
+
return new LinearService({ oauthToken: auth.token });
|
|
455
|
+
}
|
|
456
|
+
return new LinearService({ apiKey: auth.token });
|
|
442
457
|
}
|
|
@@ -106,8 +106,11 @@ function parseBulletList(state, line) {
|
|
|
106
106
|
return false;
|
|
107
107
|
}
|
|
108
108
|
const items = [];
|
|
109
|
-
while (state.i < state.lines.length
|
|
109
|
+
while (state.i < state.lines.length) {
|
|
110
110
|
const m = state.lines[state.i].match(BULLET_RE);
|
|
111
|
+
if (!m) {
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
111
114
|
items.push({
|
|
112
115
|
type: "listItem",
|
|
113
116
|
content: [{ type: "paragraph", content: parseInline(m[1]) }],
|
|
@@ -122,9 +125,11 @@ function parseOrderedList(state, line) {
|
|
|
122
125
|
return false;
|
|
123
126
|
}
|
|
124
127
|
const items = [];
|
|
125
|
-
while (state.i < state.lines.length
|
|
126
|
-
ORDERED_RE.test(state.lines[state.i])) {
|
|
128
|
+
while (state.i < state.lines.length) {
|
|
127
129
|
const m = state.lines[state.i].match(ORDERED_RE);
|
|
130
|
+
if (!m) {
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
128
133
|
items.push({
|
|
129
134
|
type: "listItem",
|
|
130
135
|
content: [{ type: "paragraph", content: parseInline(m[1]) }],
|
|
@@ -139,9 +144,11 @@ function parseBlockquote(state) {
|
|
|
139
144
|
return false;
|
|
140
145
|
}
|
|
141
146
|
const quoteLines = [];
|
|
142
|
-
while (state.i < state.lines.length
|
|
143
|
-
BLOCKQUOTE_RE.test(state.lines[state.i])) {
|
|
147
|
+
while (state.i < state.lines.length) {
|
|
144
148
|
const m = state.lines[state.i].match(BLOCKQUOTE_RE);
|
|
149
|
+
if (!m) {
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
145
152
|
quoteLines.push(m[1]);
|
|
146
153
|
state.i++;
|
|
147
154
|
}
|
|
@@ -283,7 +290,7 @@ function findEarliestInlineMatch(text) {
|
|
|
283
290
|
const codeMatch = text.match(INLINE_CODE_RE);
|
|
284
291
|
if (codeMatch) {
|
|
285
292
|
candidates.push({
|
|
286
|
-
index: codeMatch.index,
|
|
293
|
+
index: codeMatch.index ?? 0,
|
|
287
294
|
length: codeMatch[0].length,
|
|
288
295
|
innerText: codeMatch[1],
|
|
289
296
|
marks: [{ type: "code" }],
|
|
@@ -292,7 +299,7 @@ function findEarliestInlineMatch(text) {
|
|
|
292
299
|
const linkMatch = text.match(INLINE_LINK_RE);
|
|
293
300
|
if (linkMatch) {
|
|
294
301
|
candidates.push({
|
|
295
|
-
index: linkMatch.index,
|
|
302
|
+
index: linkMatch.index ?? 0,
|
|
296
303
|
length: linkMatch[0].length,
|
|
297
304
|
innerText: linkMatch[1],
|
|
298
305
|
marks: [{ type: "link", attrs: { href: linkMatch[2] } }],
|
|
@@ -301,7 +308,7 @@ function findEarliestInlineMatch(text) {
|
|
|
301
308
|
const boldMatch = text.match(INLINE_BOLD_RE);
|
|
302
309
|
if (boldMatch) {
|
|
303
310
|
candidates.push({
|
|
304
|
-
index: boldMatch.index,
|
|
311
|
+
index: boldMatch.index ?? 0,
|
|
305
312
|
length: boldMatch[0].length,
|
|
306
313
|
innerText: boldMatch[1] ?? boldMatch[2],
|
|
307
314
|
marks: [{ type: "bold" }],
|
|
@@ -310,7 +317,7 @@ function findEarliestInlineMatch(text) {
|
|
|
310
317
|
const italicMatch = text.match(INLINE_ITALIC_RE);
|
|
311
318
|
if (italicMatch) {
|
|
312
319
|
candidates.push({
|
|
313
|
-
index: italicMatch.index,
|
|
320
|
+
index: italicMatch.index ?? 0,
|
|
314
321
|
length: italicMatch[0].length,
|
|
315
322
|
innerText: italicMatch[1] ?? italicMatch[2],
|
|
316
323
|
marks: [{ type: "italic" }],
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Command, OptionValues } from "commander";
|
|
2
|
+
/**
|
|
3
|
+
* Extract root command options from inside a subcommand action handler.
|
|
4
|
+
*
|
|
5
|
+
* Commander guarantees `command.parent` exists inside any subcommand action,
|
|
6
|
+
* and `command.parent.parent` exists inside a nested subcommand action
|
|
7
|
+
* (e.g. `el-linear comments create` — the `create` command is nested under
|
|
8
|
+
* `comments`, which is nested under the root program). The non-null
|
|
9
|
+
* assertions live here so call sites can stay clean and typed.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getRootOpts(command: Command): OptionValues;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract root command options from inside a subcommand action handler.
|
|
3
|
+
*
|
|
4
|
+
* Commander guarantees `command.parent` exists inside any subcommand action,
|
|
5
|
+
* and `command.parent.parent` exists inside a nested subcommand action
|
|
6
|
+
* (e.g. `el-linear comments create` — the `create` command is nested under
|
|
7
|
+
* `comments`, which is nested under the root program). The non-null
|
|
8
|
+
* assertions live here so call sites can stay clean and typed.
|
|
9
|
+
*/
|
|
10
|
+
export function getRootOpts(command) {
|
|
11
|
+
// biome-ignore lint/style/noNonNullAssertion: command.parent / .parent.parent are guaranteed by commander inside subcommand actions; see docstring
|
|
12
|
+
return (command.parent?.parent ?? command.parent).opts();
|
|
13
|
+
}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
export declare function parsePositiveInt(value: string, flagName: string): number;
|
|
2
|
+
/**
|
|
3
|
+
* Parse a single priority value (for `issues create --priority`, `issues update --priority`).
|
|
4
|
+
*
|
|
5
|
+
* Accepts:
|
|
6
|
+
* - keywords: none | urgent | high | medium | normal | low
|
|
7
|
+
* - numbers: 0 (no priority), 1 (urgent), 2 (high), 3 (medium), 4 (low)
|
|
8
|
+
*/
|
|
2
9
|
export declare function validatePriority(value: string): number;
|
|
3
10
|
export declare function validateHexColor(value: string): string;
|
|
4
11
|
export declare function validateIsoDate(value: string): string;
|
package/dist/utils/validators.js
CHANGED
|
@@ -8,14 +8,21 @@ export function parsePositiveInt(value, flagName) {
|
|
|
8
8
|
}
|
|
9
9
|
return n;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Parse a single priority value (for `issues create --priority`, `issues update --priority`).
|
|
13
|
+
*
|
|
14
|
+
* Accepts:
|
|
15
|
+
* - keywords: none | urgent | high | medium | normal | low
|
|
16
|
+
* - numbers: 0 (no priority), 1 (urgent), 2 (high), 3 (medium), 4 (low)
|
|
17
|
+
*/
|
|
11
18
|
export function validatePriority(value) {
|
|
12
19
|
const asName = PRIORITY_NAMES[value.toLowerCase()];
|
|
13
|
-
if (asName !== undefined
|
|
20
|
+
if (asName !== undefined) {
|
|
14
21
|
return asName;
|
|
15
22
|
}
|
|
16
23
|
const n = Number.parseInt(value, 10);
|
|
17
|
-
if (Number.isNaN(n) || n <
|
|
18
|
-
throw invalidParameterError("--priority", `"${value}" is not valid. Use names (urgent, high, medium/normal, low) or numbers (
|
|
24
|
+
if (Number.isNaN(n) || n < 0 || n > 4) {
|
|
25
|
+
throw invalidParameterError("--priority", `"${value}" is not valid. Use names (none, urgent, high, medium/normal, low) or numbers (0-4).`);
|
|
19
26
|
}
|
|
20
27
|
return n;
|
|
21
28
|
}
|
|
@@ -41,6 +48,9 @@ export function splitList(value) {
|
|
|
41
48
|
.map((s) => s.trim())
|
|
42
49
|
.filter((s) => s.length > 0);
|
|
43
50
|
}
|
|
51
|
+
// Shared keyword → Linear priority number map. `none` and `0` mean "No priority"
|
|
52
|
+
// (Linear stores it as a real state, not absence). `1..4` are the rated priorities,
|
|
53
|
+
// `urgent` (1) being the highest.
|
|
44
54
|
const PRIORITY_NAMES = {
|
|
45
55
|
none: 0,
|
|
46
56
|
urgent: 1,
|
|
@@ -50,17 +60,7 @@ const PRIORITY_NAMES = {
|
|
|
50
60
|
low: 4,
|
|
51
61
|
};
|
|
52
62
|
export function parsePriorityFilter(value) {
|
|
53
|
-
return splitList(value).map((item) =>
|
|
54
|
-
const asName = PRIORITY_NAMES[item.toLowerCase()];
|
|
55
|
-
if (asName !== undefined) {
|
|
56
|
-
return asName;
|
|
57
|
-
}
|
|
58
|
-
const n = Number.parseInt(item, 10);
|
|
59
|
-
if (Number.isNaN(n) || n < 0 || n > 4) {
|
|
60
|
-
throw invalidParameterError("--priority", `"${item}" is not valid. Use names (urgent, high, medium, low, none) or numbers (0-4).`);
|
|
61
|
-
}
|
|
62
|
-
return n;
|
|
63
|
-
});
|
|
63
|
+
return splitList(value).map((item) => validatePriority(item));
|
|
64
64
|
}
|
|
65
65
|
export const PRIORITY_LABELS = {
|
|
66
66
|
0: "No priority",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enrichlayer/el-linear",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "A pragmatic CLI for Linear.app — deterministic team/label/member resolution, structured issue validation, configurable term enforcement, and a GraphQL escape hatch.",
|
|
5
5
|
"main": "dist/main.js",
|
|
6
6
|
"types": "dist/main.d.ts",
|