@elnora-ai/linear 1.0.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/.claude-plugin/marketplace.json +19 -0
- package/.claude-plugin/plugin.json +19 -0
- package/CHANGELOG.md +29 -0
- package/LICENSE +201 -0
- package/README.md +61 -0
- package/agents/linear-issue-creator.md +45 -0
- package/agents/linear-issue-reviewer.md +44 -0
- package/agents/linear-issue-updater.md +45 -0
- package/agents/linear-url-to-issues.md +51 -0
- package/commands/linear-bulk.md +42 -0
- package/commands/linear-cleanup.md +45 -0
- package/commands/linear-curator-run.md +39 -0
- package/commands/linear-my-issues.md +25 -0
- package/commands/linear-search.md +32 -0
- package/commands/linear-sync.md +54 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +126 -0
- package/dist/cli.js.map +1 -0
- package/dist/client/auth.d.ts +21 -0
- package/dist/client/auth.d.ts.map +1 -0
- package/dist/client/auth.js +74 -0
- package/dist/client/auth.js.map +1 -0
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +3 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/linear-client.d.ts +5 -0
- package/dist/client/linear-client.d.ts.map +1 -0
- package/dist/client/linear-client.js +18 -0
- package/dist/client/linear-client.js.map +1 -0
- package/dist/commands/bulk.d.ts +39 -0
- package/dist/commands/bulk.d.ts.map +1 -0
- package/dist/commands/bulk.js +103 -0
- package/dist/commands/bulk.js.map +1 -0
- package/dist/commands/cleanup.d.ts +39 -0
- package/dist/commands/cleanup.d.ts.map +1 -0
- package/dist/commands/cleanup.js +100 -0
- package/dist/commands/cleanup.js.map +1 -0
- package/dist/commands/curator.d.ts +23 -0
- package/dist/commands/curator.d.ts.map +1 -0
- package/dist/commands/curator.js +66 -0
- package/dist/commands/curator.js.map +1 -0
- package/dist/commands/index.d.ts +7 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +7 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/my-issues.d.ts +7 -0
- package/dist/commands/my-issues.d.ts.map +1 -0
- package/dist/commands/my-issues.js +24 -0
- package/dist/commands/my-issues.js.map +1 -0
- package/dist/commands/search.d.ts +20 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +54 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/sync.d.ts +87 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +229 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +4 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +12 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +140 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/types.d.ts +133 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +13 -0
- package/dist/config/types.js.map +1 -0
- package/dist/output/formatter.d.ts +16 -0
- package/dist/output/formatter.d.ts.map +1 -0
- package/dist/output/formatter.js +34 -0
- package/dist/output/formatter.js.map +1 -0
- package/dist/output/index.d.ts +2 -0
- package/dist/output/index.d.ts.map +1 -0
- package/dist/output/index.js +2 -0
- package/dist/output/index.js.map +1 -0
- package/dist/signals/external-command.d.ts +30 -0
- package/dist/signals/external-command.d.ts.map +1 -0
- package/dist/signals/external-command.js +96 -0
- package/dist/signals/external-command.js.map +1 -0
- package/dist/signals/index.d.ts +4 -0
- package/dist/signals/index.d.ts.map +1 -0
- package/dist/signals/index.js +4 -0
- package/dist/signals/index.js.map +1 -0
- package/dist/signals/registry.d.ts +5 -0
- package/dist/signals/registry.d.ts.map +1 -0
- package/dist/signals/registry.js +29 -0
- package/dist/signals/registry.js.map +1 -0
- package/dist/signals/types.d.ts +25 -0
- package/dist/signals/types.d.ts.map +1 -0
- package/dist/signals/types.js +9 -0
- package/dist/signals/types.js.map +1 -0
- package/package.json +76 -0
- package/references/projects.example.json +26 -0
- package/references/projects.placeholder.json +6 -0
- package/references/repos.example.json +21 -0
- package/references/repos.placeholder.json +6 -0
- package/references/signal-sources.example.json +42 -0
- package/references/signal-sources.placeholder.json +6 -0
- package/references/slack.example.json +10 -0
- package/references/slack.placeholder.json +8 -0
- package/references/teams.example.json +21 -0
- package/references/teams.placeholder.json +6 -0
- package/references/users.example.json +18 -0
- package/references/users.placeholder.json +6 -0
- package/references/workflows.example.json +44 -0
- package/references/workflows.placeholder.json +7 -0
- package/schemas/projects.json +47 -0
- package/schemas/repos.json +41 -0
- package/schemas/signal-sources.json +90 -0
- package/schemas/slack.json +45 -0
- package/schemas/teams.json +43 -0
- package/schemas/users.json +41 -0
- package/schemas/workflows.json +61 -0
- package/skills/linear-workspace/SKILL.md +52 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// `elnora-linear cleanup` — find stale Linear issues and act on them.
|
|
2
|
+
//
|
|
3
|
+
// Default behaviour is dry-run. `--yes` commits the mutations.
|
|
4
|
+
// Default state filter is Todo + Backlog (issues that haven't entered active work).
|
|
5
|
+
// Default `--action` is `comment` (least destructive).
|
|
6
|
+
import { getLinearClient } from "../client/index.js";
|
|
7
|
+
/** Pure: given options and the candidate issues, compute the plan. */
|
|
8
|
+
export function buildCleanupPlan(opts, issues, now = new Date()) {
|
|
9
|
+
const cutoffMs = now.getTime() - opts.inactiveDays * 24 * 60 * 60 * 1000;
|
|
10
|
+
const stale = issues.filter((i) => i.updatedAt.getTime() < cutoffMs);
|
|
11
|
+
const actions = stale.map((issue) => {
|
|
12
|
+
const daysInactive = Math.floor((now.getTime() - issue.updatedAt.getTime()) / (24 * 60 * 60 * 1000));
|
|
13
|
+
const proposed = {};
|
|
14
|
+
if (opts.action === "close")
|
|
15
|
+
proposed.setStateType = "completed";
|
|
16
|
+
if (opts.action === "cancel")
|
|
17
|
+
proposed.setStateType = "canceled";
|
|
18
|
+
if (opts.message)
|
|
19
|
+
proposed.addComment = opts.message;
|
|
20
|
+
else if (opts.action === "comment") {
|
|
21
|
+
proposed.addComment = `This issue has been inactive for ${daysInactive} days. Closing or refreshing?`;
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
issueIdentifier: issue.identifier,
|
|
25
|
+
issueTitle: issue.title,
|
|
26
|
+
currentState: issue.state,
|
|
27
|
+
daysInactive,
|
|
28
|
+
proposed,
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
return { actions, totalConsidered: issues.length, dryRun: !opts.yes };
|
|
32
|
+
}
|
|
33
|
+
/** Pure: format a plan for the user. */
|
|
34
|
+
export function formatCleanupPlan(plan, mode) {
|
|
35
|
+
if (mode === "json")
|
|
36
|
+
return JSON.stringify(plan, null, 2);
|
|
37
|
+
const header = plan.dryRun
|
|
38
|
+
? `DRY RUN — ${plan.actions.length} of ${plan.totalConsidered} considered issues are stale (pass --yes to commit)`
|
|
39
|
+
: `Acted on ${plan.actions.length} stale issues (out of ${plan.totalConsidered} considered)`;
|
|
40
|
+
if (plan.actions.length === 0)
|
|
41
|
+
return `${header}\n (nothing to do)`;
|
|
42
|
+
const lines = plan.actions.map((a) => {
|
|
43
|
+
const ops = [];
|
|
44
|
+
if (a.proposed.setStateType)
|
|
45
|
+
ops.push(`state → ${a.proposed.setStateType}`);
|
|
46
|
+
if (a.proposed.addComment)
|
|
47
|
+
ops.push("+ comment");
|
|
48
|
+
return ` ${a.issueIdentifier} ${a.daysInactive}d inactive ${ops.join(" | ")} ${a.issueTitle}`;
|
|
49
|
+
});
|
|
50
|
+
return [header, ...lines].join("\n");
|
|
51
|
+
}
|
|
52
|
+
async function findStateByType(client, teamId, type) {
|
|
53
|
+
const team = await client.team(teamId);
|
|
54
|
+
const states = await team.states();
|
|
55
|
+
const match = states.nodes.find((s) => s.type === type);
|
|
56
|
+
if (!match)
|
|
57
|
+
throw new Error(`Team ${team.key} has no workflow state of type "${type}".`);
|
|
58
|
+
return match.id;
|
|
59
|
+
}
|
|
60
|
+
export async function runCleanup(opts) {
|
|
61
|
+
const client = await getLinearClient({ allowPrompt: true });
|
|
62
|
+
const states = opts.states && opts.states.length > 0 ? opts.states : ["Todo", "Backlog"];
|
|
63
|
+
const filter = {
|
|
64
|
+
state: { name: { in: states } },
|
|
65
|
+
};
|
|
66
|
+
if (opts.team)
|
|
67
|
+
filter.team = { key: { eq: opts.team } };
|
|
68
|
+
const issuesResult = await client.issues({ filter, first: opts.limit });
|
|
69
|
+
const fetched = issuesResult.nodes;
|
|
70
|
+
const projected = await Promise.all(fetched.map(async (issue) => {
|
|
71
|
+
const state = await issue.state;
|
|
72
|
+
return {
|
|
73
|
+
identifier: issue.identifier,
|
|
74
|
+
title: issue.title,
|
|
75
|
+
state: state?.name,
|
|
76
|
+
updatedAt: issue.updatedAt,
|
|
77
|
+
};
|
|
78
|
+
}));
|
|
79
|
+
const plan = buildCleanupPlan(opts, projected);
|
|
80
|
+
process.stdout.write(`${formatCleanupPlan(plan, opts.output)}\n`);
|
|
81
|
+
if (plan.dryRun)
|
|
82
|
+
return;
|
|
83
|
+
const indexByIdentifier = new Map(fetched.map((i) => [i.identifier, i]));
|
|
84
|
+
for (const action of plan.actions) {
|
|
85
|
+
const issue = indexByIdentifier.get(action.issueIdentifier);
|
|
86
|
+
if (!issue)
|
|
87
|
+
continue;
|
|
88
|
+
if (action.proposed.setStateType) {
|
|
89
|
+
const team = await issue.team;
|
|
90
|
+
if (!team)
|
|
91
|
+
throw new Error(`Issue ${issue.identifier} has no team`);
|
|
92
|
+
const stateId = await findStateByType(client, team.id, action.proposed.setStateType);
|
|
93
|
+
await issue.update({ stateId });
|
|
94
|
+
}
|
|
95
|
+
if (action.proposed.addComment) {
|
|
96
|
+
await client.createComment({ issueId: issue.id, body: action.proposed.addComment });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=cleanup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/commands/cleanup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { OutputMode } from "../output/index.js";
|
|
2
|
+
import { type Signal } from "../signals/index.js";
|
|
3
|
+
export interface CuratorOptions {
|
|
4
|
+
/** Run only the named source (matches signal_sources[].name). */
|
|
5
|
+
source?: string;
|
|
6
|
+
referencesDir?: string;
|
|
7
|
+
output: OutputMode;
|
|
8
|
+
}
|
|
9
|
+
export interface CuratorSourceReport {
|
|
10
|
+
name: string;
|
|
11
|
+
type: string;
|
|
12
|
+
enabled: boolean;
|
|
13
|
+
signalCount: number;
|
|
14
|
+
signals: Signal[];
|
|
15
|
+
error?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface CuratorReport {
|
|
18
|
+
sources: CuratorSourceReport[];
|
|
19
|
+
}
|
|
20
|
+
export declare function runCurator(opts: CuratorOptions): Promise<CuratorReport>;
|
|
21
|
+
/** Pure: render a curator report as human-readable text. */
|
|
22
|
+
export declare function formatCuratorReport(report: CuratorReport): string;
|
|
23
|
+
//# sourceMappingURL=curator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"curator.d.ts","sourceRoot":"","sources":["../../src/commands/curator.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAqB,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAErE,MAAM,WAAW,cAAc;IAC9B,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,mBAAmB,EAAE,CAAC;CAC/B;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAiC7E;AAED,4DAA4D;AAC5D,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAqBjE"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// `elnora-linear curator-run` — collect signals from configured signal sources.
|
|
2
|
+
//
|
|
3
|
+
// This PR ships the COLLECTION + REPORTING half of the curator. A follow-up PR
|
|
4
|
+
// will add the rule engine that consumes these signals + the workflows.json
|
|
5
|
+
// rules and proposes/applies issue mutations. For now, curator-run is a
|
|
6
|
+
// diagnostic — it tells you what each configured signal source is seeing.
|
|
7
|
+
import { loadConfig } from "../config/index.js";
|
|
8
|
+
import { buildSignalSource } from "../signals/index.js";
|
|
9
|
+
export async function runCurator(opts) {
|
|
10
|
+
const cfg = loadConfig({ referencesDir: opts.referencesDir, strict: false });
|
|
11
|
+
const configured = cfg.signalSources.sources;
|
|
12
|
+
const enabledSources = configured.filter((s) => s.enabled !== false);
|
|
13
|
+
const targeted = opts.source ? enabledSources.filter((s) => s.name === opts.source) : enabledSources;
|
|
14
|
+
const now = new Date();
|
|
15
|
+
const report = { sources: [] };
|
|
16
|
+
for (const sourceConfig of targeted) {
|
|
17
|
+
const entry = {
|
|
18
|
+
name: sourceConfig.name,
|
|
19
|
+
type: sourceConfig.type,
|
|
20
|
+
enabled: sourceConfig.enabled !== false,
|
|
21
|
+
signalCount: 0,
|
|
22
|
+
signals: [],
|
|
23
|
+
};
|
|
24
|
+
try {
|
|
25
|
+
const source = buildSignalSource(sourceConfig);
|
|
26
|
+
const signals = await source.collect({ now });
|
|
27
|
+
entry.signalCount = signals.length;
|
|
28
|
+
entry.signals = signals;
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
entry.error = err instanceof Error ? err.message : String(err);
|
|
32
|
+
}
|
|
33
|
+
report.sources.push(entry);
|
|
34
|
+
}
|
|
35
|
+
if (opts.output === "json") {
|
|
36
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
process.stdout.write(formatCuratorReport(report));
|
|
40
|
+
}
|
|
41
|
+
return report;
|
|
42
|
+
}
|
|
43
|
+
/** Pure: render a curator report as human-readable text. */
|
|
44
|
+
export function formatCuratorReport(report) {
|
|
45
|
+
if (report.sources.length === 0) {
|
|
46
|
+
return "No enabled signal sources configured. Add entries to references/signal-sources.json and rerun.\n";
|
|
47
|
+
}
|
|
48
|
+
const lines = [];
|
|
49
|
+
for (const s of report.sources) {
|
|
50
|
+
if (s.error) {
|
|
51
|
+
lines.push(`[!!] ${s.name} (${s.type}) — error: ${s.error}`);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
lines.push(`[ok] ${s.name} (${s.type}): ${s.signalCount} signal(s)`);
|
|
55
|
+
for (const sig of s.signals.slice(0, 10)) {
|
|
56
|
+
const id = sig.issueIdentifier ?? "-";
|
|
57
|
+
const preview = JSON.stringify(sig.payload).slice(0, 80);
|
|
58
|
+
lines.push(` ${id.padEnd(10)} ${preview}`);
|
|
59
|
+
}
|
|
60
|
+
if (s.signals.length > 10) {
|
|
61
|
+
lines.push(` … ${s.signals.length - 10} more`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return `${lines.join("\n")}\n`;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=curator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"curator.js","sourceRoot":"","sources":["../../src/commands/curator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"my-issues.d.ts","sourceRoot":"","sources":["../../src/commands/my-issues.ts"],"names":[],"mappings":"AAIA,OAAO,EAAqC,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAExF,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;CACnB;AAgBD,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAMtE"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// `elnora-linear my-issues` — list issues assigned to the current viewer.
|
|
2
|
+
import { getLinearClient } from "../client/index.js";
|
|
3
|
+
import { formatIssues } from "../output/index.js";
|
|
4
|
+
async function projectIssue(issue) {
|
|
5
|
+
const [state, team, project] = await Promise.all([issue.state, issue.team, issue.project]);
|
|
6
|
+
return {
|
|
7
|
+
identifier: issue.identifier,
|
|
8
|
+
title: issue.title,
|
|
9
|
+
state: state?.name,
|
|
10
|
+
team: team?.key,
|
|
11
|
+
project: project?.name,
|
|
12
|
+
priority: issue.priority,
|
|
13
|
+
url: issue.url,
|
|
14
|
+
updatedAt: issue.updatedAt.toISOString(),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export async function runMyIssues(opts) {
|
|
18
|
+
const client = await getLinearClient({ allowPrompt: true });
|
|
19
|
+
const me = await client.viewer;
|
|
20
|
+
const result = await me.assignedIssues({ first: opts.limit });
|
|
21
|
+
const projected = await Promise.all(result.nodes.map(projectIssue));
|
|
22
|
+
process.stdout.write(`${formatIssues(projected, opts.output)}\n`);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=my-issues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"my-issues.js","sourceRoot":"","sources":["../../src/commands/my-issues.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAG1E,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAuB,YAAY,EAAmB,MAAM,oBAAoB,CAAC;AAOxF,KAAK,UAAU,YAAY,CAAC,KAAY;IACvC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3F,OAAO;QACN,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,KAAK,EAAE,KAAK,EAAE,IAAI;QAClB,IAAI,EAAE,IAAI,EAAE,GAAG;QACf,OAAO,EAAE,OAAO,EAAE,IAAI;QACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,EAAE;KACxC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAqB;IACtD,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;IAC/B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;IACpE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACnE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { LinearClient } from "@linear/sdk";
|
|
2
|
+
import { type OutputMode } from "../output/index.js";
|
|
3
|
+
export interface SearchOptions {
|
|
4
|
+
query?: string;
|
|
5
|
+
team?: string;
|
|
6
|
+
assignee?: string;
|
|
7
|
+
state?: string;
|
|
8
|
+
limit: number;
|
|
9
|
+
output: OutputMode;
|
|
10
|
+
}
|
|
11
|
+
export type IssueFilter = Record<string, unknown>;
|
|
12
|
+
/**
|
|
13
|
+
* Translate SearchOptions into a Linear IssueFilter.
|
|
14
|
+
*
|
|
15
|
+
* Pure function except for the special "me" assignee path, which needs to look up
|
|
16
|
+
* the current viewer's user id. Pass `client` only when assignee="me".
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildFilter(opts: SearchOptions, client?: LinearClient): Promise<IssueFilter>;
|
|
19
|
+
export declare function runSearch(opts: SearchOptions): Promise<void>;
|
|
20
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAS,YAAY,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,EAAqC,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAExF,MAAM,WAAW,aAAa;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;CACnB;AAID,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAElD;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAqBlG;AAiBD,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAMlE"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// `elnora-linear search` — query Linear issues with optional filters.
|
|
2
|
+
import { getLinearClient } from "../client/index.js";
|
|
3
|
+
import { formatIssues } from "../output/index.js";
|
|
4
|
+
/**
|
|
5
|
+
* Translate SearchOptions into a Linear IssueFilter.
|
|
6
|
+
*
|
|
7
|
+
* Pure function except for the special "me" assignee path, which needs to look up
|
|
8
|
+
* the current viewer's user id. Pass `client` only when assignee="me".
|
|
9
|
+
*/
|
|
10
|
+
export async function buildFilter(opts, client) {
|
|
11
|
+
const filter = {};
|
|
12
|
+
if (opts.query) {
|
|
13
|
+
filter.searchableContent = { contains: opts.query };
|
|
14
|
+
}
|
|
15
|
+
if (opts.team) {
|
|
16
|
+
filter.team = { key: { eq: opts.team } };
|
|
17
|
+
}
|
|
18
|
+
if (opts.state) {
|
|
19
|
+
filter.state = { name: { eqIgnoreCase: opts.state } };
|
|
20
|
+
}
|
|
21
|
+
if (opts.assignee === "me") {
|
|
22
|
+
if (!client) {
|
|
23
|
+
throw new Error("buildFilter requires a LinearClient when assignee='me' to resolve the viewer's id.");
|
|
24
|
+
}
|
|
25
|
+
const me = await client.viewer;
|
|
26
|
+
filter.assignee = { id: { eq: me.id } };
|
|
27
|
+
}
|
|
28
|
+
else if (opts.assignee) {
|
|
29
|
+
filter.assignee = { name: { eqIgnoreCase: opts.assignee } };
|
|
30
|
+
}
|
|
31
|
+
return filter;
|
|
32
|
+
}
|
|
33
|
+
async function projectIssue(issue) {
|
|
34
|
+
const [state, assignee, team, project] = await Promise.all([issue.state, issue.assignee, issue.team, issue.project]);
|
|
35
|
+
return {
|
|
36
|
+
identifier: issue.identifier,
|
|
37
|
+
title: issue.title,
|
|
38
|
+
state: state?.name,
|
|
39
|
+
assignee: assignee?.name,
|
|
40
|
+
team: team?.key,
|
|
41
|
+
project: project?.name,
|
|
42
|
+
priority: issue.priority,
|
|
43
|
+
url: issue.url,
|
|
44
|
+
updatedAt: issue.updatedAt.toISOString(),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export async function runSearch(opts) {
|
|
48
|
+
const client = await getLinearClient({ allowPrompt: true });
|
|
49
|
+
const filter = await buildFilter(opts, client);
|
|
50
|
+
const result = await client.issues({ filter, first: opts.limit });
|
|
51
|
+
const projected = await Promise.all(result.nodes.map(projectIssue));
|
|
52
|
+
process.stdout.write(`${formatIssues(projected, opts.output)}\n`);
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { type ReferenceName } from "../config/index.js";
|
|
2
|
+
import type { OutputMode } from "../output/index.js";
|
|
3
|
+
export type AutoSyncTarget = "teams" | "projects" | "users" | "workflows";
|
|
4
|
+
export declare const AUTO_SYNC_TARGETS: AutoSyncTarget[];
|
|
5
|
+
export interface SyncOptions {
|
|
6
|
+
referencesDir?: string;
|
|
7
|
+
output: OutputMode;
|
|
8
|
+
}
|
|
9
|
+
export interface SyncImportOptions extends SyncOptions {
|
|
10
|
+
from: string;
|
|
11
|
+
}
|
|
12
|
+
export interface SyncReport {
|
|
13
|
+
target: string;
|
|
14
|
+
written: number;
|
|
15
|
+
path: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Resolves the directory the sync command should write to.
|
|
19
|
+
*
|
|
20
|
+
* Refuses to write to the bundled `references/` dir shipped in the npm package
|
|
21
|
+
* (would corrupt the install). Instead, falls back to ~/.config/elnora-linear/
|
|
22
|
+
* (auto-creating it).
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveSyncWriteDir(override?: string): string;
|
|
25
|
+
export interface MappedTeam {
|
|
26
|
+
key: string;
|
|
27
|
+
name: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
}
|
|
30
|
+
export declare function mapTeam(t: {
|
|
31
|
+
key: string;
|
|
32
|
+
name: string;
|
|
33
|
+
description?: string | null;
|
|
34
|
+
}): MappedTeam;
|
|
35
|
+
type LinearProjectState = "backlog" | "planned" | "started" | "paused" | "completed" | "canceled" | string;
|
|
36
|
+
type SchemaProjectStatus = "Planned" | "In Progress" | "Backlog" | "Completed" | "Canceled";
|
|
37
|
+
export declare function mapProjectStatus(linearState: LinearProjectState | null | undefined): SchemaProjectStatus | undefined;
|
|
38
|
+
export interface MappedProject {
|
|
39
|
+
name: string;
|
|
40
|
+
team: string;
|
|
41
|
+
status?: SchemaProjectStatus;
|
|
42
|
+
description?: string;
|
|
43
|
+
}
|
|
44
|
+
export declare function mapProject(p: {
|
|
45
|
+
name: string;
|
|
46
|
+
description?: string | null;
|
|
47
|
+
state?: string | null;
|
|
48
|
+
}, teamKey: string): MappedProject;
|
|
49
|
+
export interface MappedUser {
|
|
50
|
+
key: string;
|
|
51
|
+
name: string;
|
|
52
|
+
email?: string;
|
|
53
|
+
linear_user_id: string;
|
|
54
|
+
}
|
|
55
|
+
export declare function mapUser(u: {
|
|
56
|
+
id: string;
|
|
57
|
+
name: string;
|
|
58
|
+
email?: string | null;
|
|
59
|
+
displayName?: string | null;
|
|
60
|
+
}): MappedUser;
|
|
61
|
+
export type WorkflowStateType = "backlog" | "unstarted" | "started" | "completed" | "canceled" | "triage";
|
|
62
|
+
export interface MappedWorkflowState {
|
|
63
|
+
name: string;
|
|
64
|
+
type: WorkflowStateType;
|
|
65
|
+
}
|
|
66
|
+
export declare function mapWorkflowState(s: {
|
|
67
|
+
name: string;
|
|
68
|
+
type: string;
|
|
69
|
+
}): MappedWorkflowState | null;
|
|
70
|
+
export declare function runSyncTarget(target: AutoSyncTarget, opts: SyncOptions): Promise<void>;
|
|
71
|
+
export declare function runSyncAll(opts: SyncOptions): Promise<void>;
|
|
72
|
+
export interface VerifyReport {
|
|
73
|
+
referencesDir: string;
|
|
74
|
+
sources: Record<ReferenceName, "user-file" | "placeholder" | "missing">;
|
|
75
|
+
}
|
|
76
|
+
export declare function runSyncVerify(opts: SyncOptions): VerifyReport;
|
|
77
|
+
export interface ImportReport {
|
|
78
|
+
written: Array<{
|
|
79
|
+
target: ReferenceName;
|
|
80
|
+
path: string;
|
|
81
|
+
}>;
|
|
82
|
+
}
|
|
83
|
+
/** Pure: given parsed JSON, decide which reference targets to write. */
|
|
84
|
+
export declare function planImport(parsed: unknown): ReferenceName[];
|
|
85
|
+
export declare function runSyncImport(opts: SyncImportOptions): ImportReport;
|
|
86
|
+
export {};
|
|
87
|
+
//# sourceMappingURL=sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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"}
|