@enrichlayer/el-linear 1.29.0 → 1.29.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.
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* connection has no top-level state filter).
|
|
19
19
|
*/
|
|
20
20
|
import { buildIssueTreeQuery, DEFAULT_TREE_DEPTH, MAX_TREE_DEPTH, } from "../../queries/issue-tree.js";
|
|
21
|
+
import { TERMINAL_STATE_TYPES } from "../../types/linear.js";
|
|
21
22
|
import { formatTree } from "../../utils/format-tree.js";
|
|
22
23
|
import { createIssuesService } from "../../utils/issues-service-bootstrap.js";
|
|
23
24
|
import { handleAsyncCommand, outputSuccess } from "../../utils/output.js";
|
|
@@ -74,10 +75,11 @@ function parseDepth(raw) {
|
|
|
74
75
|
return n;
|
|
75
76
|
}
|
|
76
77
|
/**
|
|
77
|
-
* Walk the tree depth-first and drop any node whose `state.type` is
|
|
78
|
-
* `completed`
|
|
79
|
-
* A pruned child takes its entire
|
|
80
|
-
* `issues list --no-include-closed`
|
|
78
|
+
* Walk the tree depth-first and drop any node whose `state.type` is terminal
|
|
79
|
+
* (`completed` / `canceled` / `duplicate` — `TERMINAL_STATE_TYPES`, DEV-4879).
|
|
80
|
+
* Pure function — does not mutate the input. A pruned child takes its entire
|
|
81
|
+
* subtree with it (consistent with how `issues list --no-include-closed`
|
|
82
|
+
* excludes closed work entirely — same shared constant).
|
|
81
83
|
*
|
|
82
84
|
* Assumes Linear's parent → children graph stays single-parent (a tree,
|
|
83
85
|
* not a DAG). If Linear ever ships multi-parent issues, this recursion
|
|
@@ -97,6 +99,5 @@ function pruneTerminalStates(root) {
|
|
|
97
99
|
};
|
|
98
100
|
}
|
|
99
101
|
function isTerminalState(node) {
|
|
100
|
-
|
|
101
|
-
return t === "completed" || t === "canceled";
|
|
102
|
+
return TERMINAL_STATE_TYPES.includes(node.state?.type ?? "");
|
|
102
103
|
}
|
package/dist/types/linear.d.ts
CHANGED
|
@@ -35,6 +35,17 @@ interface StateRef {
|
|
|
35
35
|
*/
|
|
36
36
|
type?: string;
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Workflow-state types treated as terminal / closed for default filtering.
|
|
40
|
+
* `issues list` / `issues search` exclude these unless `--include-closed` (or
|
|
41
|
+
* an explicit `--status`) is passed (DEV-4478).
|
|
42
|
+
*
|
|
43
|
+
* `duplicate` is included (DEV-4879) because this workspace parks resolved
|
|
44
|
+
* duplicates in a `duplicate`-typed state — they carry a `duplicate-of`
|
|
45
|
+
* relation and are semantically closed, so they must not leak into the default
|
|
46
|
+
* open-issues view the way `completed` / `canceled` don't.
|
|
47
|
+
*/
|
|
48
|
+
export declare const TERMINAL_STATE_TYPES: readonly string[];
|
|
38
49
|
interface ProjectRef {
|
|
39
50
|
id: string;
|
|
40
51
|
name: string;
|
package/dist/types/linear.js
CHANGED
|
@@ -3,4 +3,18 @@
|
|
|
3
3
|
* These represent the public API surface — GraphQL responses are
|
|
4
4
|
* transformed into these shapes at the service boundary.
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Workflow-state types treated as terminal / closed for default filtering.
|
|
8
|
+
* `issues list` / `issues search` exclude these unless `--include-closed` (or
|
|
9
|
+
* an explicit `--status`) is passed (DEV-4478).
|
|
10
|
+
*
|
|
11
|
+
* `duplicate` is included (DEV-4879) because this workspace parks resolved
|
|
12
|
+
* duplicates in a `duplicate`-typed state — they carry a `duplicate-of`
|
|
13
|
+
* relation and are semantically closed, so they must not leak into the default
|
|
14
|
+
* open-issues view the way `completed` / `canceled` don't.
|
|
15
|
+
*/
|
|
16
|
+
export const TERMINAL_STATE_TYPES = [
|
|
17
|
+
"completed",
|
|
18
|
+
"canceled",
|
|
19
|
+
"duplicate",
|
|
20
|
+
];
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* Pure rendering — does not fetch or filter. The depth bound and the
|
|
11
11
|
* terminal-state exclusion are enforced by the caller before this runs.
|
|
12
12
|
*/
|
|
13
|
+
import { TERMINAL_STATE_TYPES } from "../types/linear.js";
|
|
13
14
|
const BRANCH_TEE = "├── ";
|
|
14
15
|
const BRANCH_END = "└── ";
|
|
15
16
|
const VERTICAL = "│ ";
|
|
@@ -40,7 +41,7 @@ function formatStateSuffix(state) {
|
|
|
40
41
|
// Only annotate terminal-typed states; the renderer is otherwise
|
|
41
42
|
// state-name-agnostic so workspace-custom workflow states (e.g. "In
|
|
42
43
|
// Review") don't get a noisy suffix.
|
|
43
|
-
if (
|
|
44
|
+
if (TERMINAL_STATE_TYPES.includes(state.type)) {
|
|
44
45
|
return ` [${state.name}]`;
|
|
45
46
|
}
|
|
46
47
|
return "";
|
|
@@ -42,7 +42,8 @@ export interface SearchIssueArgs {
|
|
|
42
42
|
/** Issue states to include (e.g. `["Todo", "In Progress"]`). */
|
|
43
43
|
status?: string[];
|
|
44
44
|
/**
|
|
45
|
-
* Exclude terminal states (workflow type `completed` or
|
|
45
|
+
* Exclude terminal states (workflow type `completed`, `canceled`, or
|
|
46
|
+
* `duplicate` — see `TERMINAL_STATE_TYPES`).
|
|
46
47
|
* Default `false` for back-compat at the service layer; the CLI's
|
|
47
48
|
* `issues list` / `issues search` flip this to `true` by default
|
|
48
49
|
* (DEV-4478) and accept `--include-closed` to opt back in. When
|
|
@@ -2,6 +2,7 @@ import { isRegistryConfigured, resolveViaRegistry, } from "../config/registry-re
|
|
|
2
2
|
import { resolveUserDisplayName } from "../config/resolver.js";
|
|
3
3
|
import { ARCHIVE_ISSUE_MUTATION, BATCH_GET_ISSUES_QUERY, BATCH_RESOLVE_FOR_CREATE_QUERY, BATCH_RESOLVE_FOR_SEARCH_QUERY, BATCH_RESOLVE_FOR_UPDATE_QUERY, buildResolveLabelsByNameQuery, CREATE_ISSUE_MUTATION, DELETE_ISSUE_MUTATION, FILTERED_SEARCH_ISSUES_QUERY, GET_ISSUE_BY_ID_QUERY, GET_ISSUE_BY_IDENTIFIER_QUERY, GET_ISSUE_CLAIM_CONTEXT_QUERY, GET_ISSUE_START_CONTEXT_QUERY, GET_ISSUE_TEAM_QUERY, GET_ISSUES_QUERY, SEARCH_ISSUES_QUERY, TEAM_STARTED_STATUSES_QUERY, UPDATE_ISSUE_MUTATION, } from "../queries/issues.js";
|
|
4
4
|
import { CREATE_LABEL_MUTATION } from "../queries/labels.js";
|
|
5
|
+
import { TERMINAL_STATE_TYPES } from "../types/linear.js";
|
|
5
6
|
import { toISOStringOrNow } from "./date-format.js";
|
|
6
7
|
import { extractEmbeds } from "./embed-parser.js";
|
|
7
8
|
import { multipleMatchesError, notFoundError } from "./error-messages.js";
|
|
@@ -981,7 +982,7 @@ export class GraphQLIssuesService {
|
|
|
981
982
|
else if (filters.excludeTerminalStates) {
|
|
982
983
|
// Implicit terminal-state exclusion (DEV-4478). Explicit `status`
|
|
983
984
|
// always wins — the user already named the states they want.
|
|
984
|
-
filtered = filtered.filter((issue) =>
|
|
985
|
+
filtered = filtered.filter((issue) => !TERMINAL_STATE_TYPES.includes(issue.state?.type ?? ""));
|
|
985
986
|
}
|
|
986
987
|
if (filters.labelNames && filters.labelNames.length > 0) {
|
|
987
988
|
const lowerNames = filters.labelNames.map((n) => n.toLowerCase());
|
|
@@ -1024,7 +1025,7 @@ export class GraphQLIssuesService {
|
|
|
1024
1025
|
else if (filters.excludeTerminalStates) {
|
|
1025
1026
|
// Implicit terminal-state exclusion (DEV-4478). Explicit `status`
|
|
1026
1027
|
// always wins — the user already named the states they want.
|
|
1027
|
-
filter.state = { type: { nin: [
|
|
1028
|
+
filter.state = { type: { nin: [...TERMINAL_STATE_TYPES] } };
|
|
1028
1029
|
}
|
|
1029
1030
|
if (filters.labelNames && filters.labelNames.length > 0) {
|
|
1030
1031
|
if (filters.labelNames.length === 1) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enrichlayer/el-linear",
|
|
3
|
-
"version": "1.29.
|
|
3
|
+
"version": "1.29.1",
|
|
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",
|