@brainfile/cli 0.11.2 → 0.12.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.
@@ -0,0 +1,295 @@
1
+ "use strict";
2
+ /**
3
+ * Linear Authentication for Brainfile CLI
4
+ *
5
+ * Supports:
6
+ * 1. OAuth Device Flow (browser-based)
7
+ * 2. API Key (manual entry)
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.isLinearAuthenticated = isLinearAuthenticated;
16
+ exports.getLinearToken = getLinearToken;
17
+ exports.authenticateLinear = authenticateLinear;
18
+ exports.getLinearTeams = getLinearTeams;
19
+ exports.createLinearIssue = createLinearIssue;
20
+ exports.logoutLinear = logoutLinear;
21
+ const chalk_1 = __importDefault(require("chalk"));
22
+ const auth_store_1 = require("./auth-store");
23
+ // ============================================================================
24
+ // Constants
25
+ // ============================================================================
26
+ const LINEAR_API_URL = 'https://api.linear.app/graphql';
27
+ // ============================================================================
28
+ // Linear Auth Functions
29
+ // ============================================================================
30
+ /**
31
+ * Check if Linear is already authenticated
32
+ */
33
+ async function isLinearAuthenticated() {
34
+ return await auth_store_1.authStore.isAuthenticated('linear');
35
+ }
36
+ /**
37
+ * Get the current Linear token
38
+ */
39
+ async function getLinearToken() {
40
+ return await auth_store_1.authStore.get('linear');
41
+ }
42
+ /**
43
+ * Authenticate with Linear using API key
44
+ */
45
+ async function authenticateLinear(options) {
46
+ const { token, silent } = options;
47
+ if (!token) {
48
+ if (!silent) {
49
+ console.log('');
50
+ console.log('To authenticate with Linear, you need an API key.');
51
+ console.log('');
52
+ console.log(`Get your API key from: ${chalk_1.default.underline('https://linear.app/settings/api')}`);
53
+ console.log('');
54
+ }
55
+ return { success: false, error: 'Linear API key required. Use --token flag.' };
56
+ }
57
+ // Verify the token
58
+ const viewer = await getLinearViewer(token);
59
+ if (!viewer) {
60
+ return { success: false, error: 'Invalid API key or API key lacks required permissions' };
61
+ }
62
+ // Get organization info
63
+ const org = await getLinearOrganization(token);
64
+ const workspace = org?.name || 'Unknown';
65
+ await auth_store_1.authStore.set('linear', token, {
66
+ username: viewer.name,
67
+ workspace,
68
+ });
69
+ if (!silent) {
70
+ console.log(chalk_1.default.green('✓') + ' API key verified');
71
+ console.log(chalk_1.default.green('✓') + ` Authenticated as ${chalk_1.default.cyan(viewer.name)} in ${chalk_1.default.cyan(workspace)}`);
72
+ }
73
+ return { success: true, workspace };
74
+ }
75
+ /**
76
+ * Get Linear user info
77
+ */
78
+ async function getLinearViewer(token) {
79
+ try {
80
+ const response = await fetch(LINEAR_API_URL, {
81
+ method: 'POST',
82
+ headers: {
83
+ Authorization: token,
84
+ 'Content-Type': 'application/json',
85
+ },
86
+ body: JSON.stringify({
87
+ query: `
88
+ query {
89
+ viewer {
90
+ id
91
+ name
92
+ email
93
+ }
94
+ }
95
+ `,
96
+ }),
97
+ });
98
+ if (!response.ok) {
99
+ return null;
100
+ }
101
+ const json = await response.json();
102
+ return json.data?.viewer || null;
103
+ }
104
+ catch {
105
+ return null;
106
+ }
107
+ }
108
+ /**
109
+ * Get Linear organization info
110
+ */
111
+ async function getLinearOrganization(token) {
112
+ try {
113
+ const response = await fetch(LINEAR_API_URL, {
114
+ method: 'POST',
115
+ headers: {
116
+ Authorization: token,
117
+ 'Content-Type': 'application/json',
118
+ },
119
+ body: JSON.stringify({
120
+ query: `
121
+ query {
122
+ organization {
123
+ id
124
+ name
125
+ }
126
+ }
127
+ `,
128
+ }),
129
+ });
130
+ if (!response.ok) {
131
+ return null;
132
+ }
133
+ const json = await response.json();
134
+ return json.data?.organization || null;
135
+ }
136
+ catch {
137
+ return null;
138
+ }
139
+ }
140
+ /**
141
+ * Get Linear teams
142
+ */
143
+ async function getLinearTeams() {
144
+ const token = await getLinearToken();
145
+ if (!token) {
146
+ return [];
147
+ }
148
+ try {
149
+ const response = await fetch(LINEAR_API_URL, {
150
+ method: 'POST',
151
+ headers: {
152
+ Authorization: token,
153
+ 'Content-Type': 'application/json',
154
+ },
155
+ body: JSON.stringify({
156
+ query: `
157
+ query {
158
+ teams {
159
+ nodes {
160
+ id
161
+ name
162
+ key
163
+ }
164
+ }
165
+ }
166
+ `,
167
+ }),
168
+ });
169
+ if (!response.ok) {
170
+ return [];
171
+ }
172
+ const json = await response.json();
173
+ return json.data?.teams?.nodes || [];
174
+ }
175
+ catch {
176
+ return [];
177
+ }
178
+ }
179
+ /**
180
+ * Create a Linear issue
181
+ */
182
+ async function createLinearIssue(options) {
183
+ const token = await getLinearToken();
184
+ if (!token) {
185
+ return { success: false, error: 'Not authenticated with Linear. Run: brainfile auth linear' };
186
+ }
187
+ try {
188
+ // First, get the "Done" state ID if stateName is specified
189
+ let stateId;
190
+ if (options.stateName) {
191
+ stateId = await getStateId(token, options.teamId, options.stateName);
192
+ }
193
+ // Create the issue
194
+ const response = await fetch(LINEAR_API_URL, {
195
+ method: 'POST',
196
+ headers: {
197
+ Authorization: token,
198
+ 'Content-Type': 'application/json',
199
+ },
200
+ body: JSON.stringify({
201
+ query: `
202
+ mutation CreateIssue($input: IssueCreateInput!) {
203
+ issueCreate(input: $input) {
204
+ success
205
+ issue {
206
+ id
207
+ identifier
208
+ url
209
+ }
210
+ }
211
+ }
212
+ `,
213
+ variables: {
214
+ input: {
215
+ teamId: options.teamId,
216
+ title: options.title,
217
+ description: options.description,
218
+ priority: options.priority,
219
+ stateId,
220
+ },
221
+ },
222
+ }),
223
+ });
224
+ if (!response.ok) {
225
+ return { success: false, error: `Linear API error: ${response.status}` };
226
+ }
227
+ const json = await response.json();
228
+ if (json.errors) {
229
+ return { success: false, error: json.errors[0]?.message || 'Unknown error' };
230
+ }
231
+ const result = json.data?.issueCreate;
232
+ if (!result?.success) {
233
+ return { success: false, error: 'Failed to create issue' };
234
+ }
235
+ return {
236
+ success: true,
237
+ issueId: result.issue.identifier,
238
+ issueUrl: result.issue.url,
239
+ };
240
+ }
241
+ catch (err) {
242
+ return {
243
+ success: false,
244
+ error: err instanceof Error ? err.message : 'Unknown error creating issue',
245
+ };
246
+ }
247
+ }
248
+ /**
249
+ * Get state ID by name
250
+ */
251
+ async function getStateId(token, teamId, stateName) {
252
+ try {
253
+ const response = await fetch(LINEAR_API_URL, {
254
+ method: 'POST',
255
+ headers: {
256
+ Authorization: token,
257
+ 'Content-Type': 'application/json',
258
+ },
259
+ body: JSON.stringify({
260
+ query: `
261
+ query GetStates($teamId: String!) {
262
+ team(id: $teamId) {
263
+ states {
264
+ nodes {
265
+ id
266
+ name
267
+ type
268
+ }
269
+ }
270
+ }
271
+ }
272
+ `,
273
+ variables: { teamId },
274
+ }),
275
+ });
276
+ if (!response.ok) {
277
+ return undefined;
278
+ }
279
+ const json = await response.json();
280
+ const states = json.data?.team?.states?.nodes || [];
281
+ // Find state by name (case-insensitive)
282
+ const state = states.find((s) => s.name.toLowerCase() === stateName.toLowerCase());
283
+ return state?.id;
284
+ }
285
+ catch {
286
+ return undefined;
287
+ }
288
+ }
289
+ /**
290
+ * Logout from Linear
291
+ */
292
+ async function logoutLinear() {
293
+ await auth_store_1.authStore.clear('linear');
294
+ }
295
+ //# sourceMappingURL=linear-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear-auth.js","sourceRoot":"","sources":["../../src/utils/linear-auth.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainfile/cli",
3
- "version": "0.11.2",
3
+ "version": "0.12.1",
4
4
  "description": "Command-line interface for Brainfile task management",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -33,12 +33,13 @@
33
33
  "access": "public"
34
34
  },
35
35
  "dependencies": {
36
- "@brainfile/core": "^0.8.0",
36
+ "@brainfile/core": "^0.9.0",
37
37
  "@modelcontextprotocol/sdk": "^1.22.0",
38
38
  "chalk": "^4.1.2",
39
39
  "chokidar": "^4.0.3",
40
40
  "commander": "^12.1.0",
41
41
  "ink": "^3.2.0",
42
+ "open": "^10.1.0",
42
43
  "js-yaml": "^4.1.0",
43
44
  "react": "^17.0.2",
44
45
  "zod": "^3.25.76"