@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,308 @@
1
+ "use strict";
2
+ /**
3
+ * Authentication token storage for Brainfile CLI
4
+ *
5
+ * Stores tokens with the following priority:
6
+ * 1. System keychain (via keytar, if available)
7
+ * 2. Config file (~/.config/brainfile/auth.json)
8
+ * 3. Environment variables (read-only)
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.authStore = exports.AuthStore = void 0;
47
+ exports.getGitHubCLIToken = getGitHubCLIToken;
48
+ exports.isGitHubCLIAvailable = isGitHubCLIAvailable;
49
+ const fs = __importStar(require("fs"));
50
+ const path = __importStar(require("path"));
51
+ const child_process_1 = require("child_process");
52
+ const config_1 = require("./config");
53
+ // ============================================================================
54
+ // Constants
55
+ // ============================================================================
56
+ const SERVICE_NAME = 'brainfile';
57
+ const AUTH_FILE = path.join((0, config_1.getConfigDir)(), 'auth.json');
58
+ const ENV_VAR_MAP = {
59
+ github: ['GITHUB_TOKEN', 'GH_TOKEN'],
60
+ linear: ['LINEAR_API_KEY', 'LINEAR_TOKEN'],
61
+ };
62
+ // ============================================================================
63
+ // Keytar Integration (Optional)
64
+ // ============================================================================
65
+ let keytar = null;
66
+ let keytarChecked = false;
67
+ /**
68
+ * Try to load keytar (system keychain integration)
69
+ * Returns null if keytar is not available
70
+ */
71
+ function getKeytar() {
72
+ if (keytarChecked) {
73
+ return keytar;
74
+ }
75
+ keytarChecked = true;
76
+ try {
77
+ // Dynamic require to make keytar optional
78
+ keytar = require('keytar');
79
+ return keytar;
80
+ }
81
+ catch {
82
+ // keytar not installed or native module not built
83
+ return null;
84
+ }
85
+ }
86
+ // ============================================================================
87
+ // GitHub CLI Integration
88
+ // ============================================================================
89
+ /**
90
+ * Try to get GitHub token from gh CLI
91
+ * @returns Token from gh CLI, or null if not available
92
+ */
93
+ function getGitHubCLIToken() {
94
+ try {
95
+ const token = (0, child_process_1.execSync)('gh auth token', {
96
+ encoding: 'utf-8',
97
+ stdio: ['pipe', 'pipe', 'pipe'],
98
+ }).trim();
99
+ if (token && token.length > 0) {
100
+ return token;
101
+ }
102
+ }
103
+ catch {
104
+ // gh CLI not installed or not authenticated
105
+ }
106
+ return null;
107
+ }
108
+ /**
109
+ * Check if gh CLI is installed and authenticated
110
+ */
111
+ function isGitHubCLIAvailable() {
112
+ return getGitHubCLIToken() !== null;
113
+ }
114
+ // ============================================================================
115
+ // Auth Store Class
116
+ // ============================================================================
117
+ class AuthStore {
118
+ /**
119
+ * Get a token for a provider
120
+ * Checks: env vars → keychain → config file → gh CLI (for github)
121
+ */
122
+ async get(provider) {
123
+ // 1. Check environment variables
124
+ const envToken = this.getFromEnv(provider);
125
+ if (envToken) {
126
+ return envToken;
127
+ }
128
+ // 2. Check system keychain
129
+ const kt = getKeytar();
130
+ if (kt) {
131
+ try {
132
+ const keychainToken = await kt.getPassword(SERVICE_NAME, provider);
133
+ if (keychainToken) {
134
+ return keychainToken;
135
+ }
136
+ }
137
+ catch {
138
+ // Keychain access failed, continue to next option
139
+ }
140
+ }
141
+ // 3. Check config file
142
+ const fileToken = this.getFromFile(provider);
143
+ if (fileToken) {
144
+ return fileToken;
145
+ }
146
+ // 4. For GitHub, check gh CLI as last resort
147
+ if (provider === 'github') {
148
+ return getGitHubCLIToken();
149
+ }
150
+ return null;
151
+ }
152
+ /**
153
+ * Get stored token info (includes metadata like username)
154
+ */
155
+ async getTokenInfo(provider) {
156
+ // Check config file for metadata
157
+ const authData = this.loadAuthFile();
158
+ return authData[provider] || null;
159
+ }
160
+ /**
161
+ * Store a token for a provider
162
+ * Stores in: keychain (if available) AND config file (for metadata)
163
+ */
164
+ async set(provider, token, metadata) {
165
+ const storedToken = {
166
+ token,
167
+ savedAt: new Date().toISOString(),
168
+ ...metadata,
169
+ };
170
+ // 1. Try to store in keychain
171
+ const kt = getKeytar();
172
+ if (kt) {
173
+ try {
174
+ await kt.setPassword(SERVICE_NAME, provider, token);
175
+ }
176
+ catch {
177
+ // Keychain storage failed, will fall back to file
178
+ }
179
+ }
180
+ // 2. Store in config file (always, for metadata)
181
+ this.saveToFile(provider, storedToken);
182
+ }
183
+ /**
184
+ * Clear a token for a provider
185
+ */
186
+ async clear(provider) {
187
+ // 1. Remove from keychain
188
+ const kt = getKeytar();
189
+ if (kt) {
190
+ try {
191
+ await kt.deletePassword(SERVICE_NAME, provider);
192
+ }
193
+ catch {
194
+ // Ignore errors
195
+ }
196
+ }
197
+ // 2. Remove from config file
198
+ this.removeFromFile(provider);
199
+ }
200
+ /**
201
+ * Check if a provider is authenticated
202
+ */
203
+ async isAuthenticated(provider) {
204
+ const token = await this.get(provider);
205
+ return token !== null;
206
+ }
207
+ /**
208
+ * Get authentication status for all providers
209
+ */
210
+ async getStatus() {
211
+ const result = {
212
+ github: { authenticated: false },
213
+ linear: { authenticated: false },
214
+ };
215
+ for (const provider of ['github', 'linear']) {
216
+ // Check env first
217
+ if (this.getFromEnv(provider)) {
218
+ result[provider] = { authenticated: true, source: 'environment' };
219
+ continue;
220
+ }
221
+ // Check keychain
222
+ const kt = getKeytar();
223
+ if (kt) {
224
+ try {
225
+ const token = await kt.getPassword(SERVICE_NAME, provider);
226
+ if (token) {
227
+ const info = await this.getTokenInfo(provider);
228
+ result[provider] = {
229
+ authenticated: true,
230
+ source: 'keychain',
231
+ username: info?.username,
232
+ };
233
+ continue;
234
+ }
235
+ }
236
+ catch {
237
+ // Continue to next check
238
+ }
239
+ }
240
+ // Check config file
241
+ const fileToken = this.getFromFile(provider);
242
+ if (fileToken) {
243
+ const info = await this.getTokenInfo(provider);
244
+ result[provider] = {
245
+ authenticated: true,
246
+ source: 'config',
247
+ username: info?.username,
248
+ };
249
+ continue;
250
+ }
251
+ // For GitHub, check gh CLI
252
+ if (provider === 'github' && getGitHubCLIToken()) {
253
+ result[provider] = { authenticated: true, source: 'gh-cli' };
254
+ }
255
+ }
256
+ return result;
257
+ }
258
+ // ============================================================================
259
+ // Private Methods
260
+ // ============================================================================
261
+ getFromEnv(provider) {
262
+ const vars = ENV_VAR_MAP[provider];
263
+ for (const varName of vars) {
264
+ const value = process.env[varName];
265
+ if (value && value.length > 0) {
266
+ return value;
267
+ }
268
+ }
269
+ return null;
270
+ }
271
+ loadAuthFile() {
272
+ try {
273
+ if (fs.existsSync(AUTH_FILE)) {
274
+ const content = fs.readFileSync(AUTH_FILE, 'utf-8');
275
+ return JSON.parse(content);
276
+ }
277
+ }
278
+ catch {
279
+ // File corrupted or unreadable
280
+ }
281
+ return {};
282
+ }
283
+ saveAuthFile(data) {
284
+ (0, config_1.ensureConfigDir)();
285
+ fs.writeFileSync(AUTH_FILE, JSON.stringify(data, null, 2), {
286
+ encoding: 'utf-8',
287
+ mode: 0o600, // Owner read/write only
288
+ });
289
+ }
290
+ getFromFile(provider) {
291
+ const data = this.loadAuthFile();
292
+ return data[provider]?.token || null;
293
+ }
294
+ saveToFile(provider, tokenInfo) {
295
+ const data = this.loadAuthFile();
296
+ data[provider] = tokenInfo;
297
+ this.saveAuthFile(data);
298
+ }
299
+ removeFromFile(provider) {
300
+ const data = this.loadAuthFile();
301
+ delete data[provider];
302
+ this.saveAuthFile(data);
303
+ }
304
+ }
305
+ exports.AuthStore = AuthStore;
306
+ // Export singleton instance
307
+ exports.authStore = new AuthStore();
308
+ //# sourceMappingURL=auth-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-store.js","sourceRoot":"","sources":["../../src/utils/auth-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Configuration file management for Brainfile CLI
3
+ *
4
+ * Handles reading/writing ~/.config/brainfile/config.json for:
5
+ * - Archive destination defaults
6
+ * - GitHub connection details (owner, repo)
7
+ * - Linear connection details (teamId)
8
+ * - User preferences
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ export interface GitHubConfig {
13
+ /** GitHub repository owner (username or org) */
14
+ owner?: string;
15
+ /** GitHub repository name */
16
+ repo?: string;
17
+ /** Extra labels to add to archived issues */
18
+ labels?: string[];
19
+ }
20
+ export interface LinearConfig {
21
+ /** Linear team ID */
22
+ teamId?: string;
23
+ /** Linear project ID (optional) */
24
+ projectId?: string;
25
+ }
26
+ export interface ArchiveConfig {
27
+ /** Default archive destination: 'local' | 'github' | 'linear' */
28
+ default?: 'local' | 'github' | 'linear';
29
+ /** GitHub-specific settings */
30
+ github?: GitHubConfig;
31
+ /** Linear-specific settings */
32
+ linear?: LinearConfig;
33
+ }
34
+ export interface BrainfileConfig {
35
+ /** Archive configuration */
36
+ archive?: ArchiveConfig;
37
+ }
38
+ /**
39
+ * Get the path to the config directory
40
+ */
41
+ export declare function getConfigDir(): string;
42
+ /**
43
+ * Get the path to the config file
44
+ */
45
+ export declare function getConfigPath(): string;
46
+ /**
47
+ * Ensure the config directory exists
48
+ */
49
+ export declare function ensureConfigDir(): void;
50
+ /**
51
+ * Load the config file
52
+ * @returns Config object, or empty object if file doesn't exist
53
+ */
54
+ export declare function loadConfig(): BrainfileConfig;
55
+ /**
56
+ * Save the config file
57
+ * @param config - Config object to save
58
+ */
59
+ export declare function saveConfig(config: BrainfileConfig): void;
60
+ /**
61
+ * Update specific config values (merges with existing)
62
+ * @param updates - Partial config to merge
63
+ */
64
+ export declare function updateConfig(updates: Partial<BrainfileConfig>): BrainfileConfig;
65
+ /**
66
+ * Get archive configuration with defaults
67
+ */
68
+ export declare function getArchiveConfig(): ArchiveConfig;
69
+ /**
70
+ * Set archive default destination
71
+ */
72
+ export declare function setArchiveDefault(destination: 'local' | 'github' | 'linear'): void;
73
+ /**
74
+ * Set GitHub configuration
75
+ */
76
+ export declare function setGitHubConfig(github: GitHubConfig): void;
77
+ /**
78
+ * Set Linear configuration
79
+ */
80
+ export declare function setLinearConfig(linear: LinearConfig): void;
81
+ /**
82
+ * Get the effective archive destination
83
+ * Priority: brainfile.md archive.destination > config default > 'local'
84
+ *
85
+ * @param brainfileDestination - Destination from brainfile.md (if any)
86
+ * @returns The effective destination
87
+ */
88
+ export declare function getEffectiveArchiveDestination(brainfileDestination?: string): 'local' | 'github' | 'linear';
89
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAUH,MAAM,WAAW,YAAY;IAC3B,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,qBAAqB;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACxC,+BAA+B;IAC/B,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,+BAA+B;IAC/B,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,4BAA4B;IAC5B,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAaD;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAItC;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,eAAe,CAW5C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAMxD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,CAK/E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAGhD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAKlF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAK1D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAK1D;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAC5C,oBAAoB,CAAC,EAAE,MAAM,GAC5B,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAc/B"}
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+ /**
3
+ * Configuration file management for Brainfile CLI
4
+ *
5
+ * Handles reading/writing ~/.config/brainfile/config.json for:
6
+ * - Archive destination defaults
7
+ * - GitHub connection details (owner, repo)
8
+ * - Linear connection details (teamId)
9
+ * - User preferences
10
+ *
11
+ * @packageDocumentation
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.getConfigDir = getConfigDir;
48
+ exports.getConfigPath = getConfigPath;
49
+ exports.ensureConfigDir = ensureConfigDir;
50
+ exports.loadConfig = loadConfig;
51
+ exports.saveConfig = saveConfig;
52
+ exports.updateConfig = updateConfig;
53
+ exports.getArchiveConfig = getArchiveConfig;
54
+ exports.setArchiveDefault = setArchiveDefault;
55
+ exports.setGitHubConfig = setGitHubConfig;
56
+ exports.setLinearConfig = setLinearConfig;
57
+ exports.getEffectiveArchiveDestination = getEffectiveArchiveDestination;
58
+ const fs = __importStar(require("fs"));
59
+ const path = __importStar(require("path"));
60
+ const os = __importStar(require("os"));
61
+ // ============================================================================
62
+ // Constants
63
+ // ============================================================================
64
+ const CONFIG_DIR = path.join(os.homedir(), '.config', 'brainfile');
65
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
66
+ // ============================================================================
67
+ // Config Functions
68
+ // ============================================================================
69
+ /**
70
+ * Get the path to the config directory
71
+ */
72
+ function getConfigDir() {
73
+ return CONFIG_DIR;
74
+ }
75
+ /**
76
+ * Get the path to the config file
77
+ */
78
+ function getConfigPath() {
79
+ return CONFIG_FILE;
80
+ }
81
+ /**
82
+ * Ensure the config directory exists
83
+ */
84
+ function ensureConfigDir() {
85
+ if (!fs.existsSync(CONFIG_DIR)) {
86
+ fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
87
+ }
88
+ }
89
+ /**
90
+ * Load the config file
91
+ * @returns Config object, or empty object if file doesn't exist
92
+ */
93
+ function loadConfig() {
94
+ try {
95
+ if (fs.existsSync(CONFIG_FILE)) {
96
+ const content = fs.readFileSync(CONFIG_FILE, 'utf-8');
97
+ return JSON.parse(content);
98
+ }
99
+ }
100
+ catch (error) {
101
+ // If file is corrupted, return empty config
102
+ console.error(`Warning: Could not read config file: ${error}`);
103
+ }
104
+ return {};
105
+ }
106
+ /**
107
+ * Save the config file
108
+ * @param config - Config object to save
109
+ */
110
+ function saveConfig(config) {
111
+ ensureConfigDir();
112
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), {
113
+ encoding: 'utf-8',
114
+ mode: 0o600, // Owner read/write only
115
+ });
116
+ }
117
+ /**
118
+ * Update specific config values (merges with existing)
119
+ * @param updates - Partial config to merge
120
+ */
121
+ function updateConfig(updates) {
122
+ const current = loadConfig();
123
+ const updated = deepMerge(current, updates);
124
+ saveConfig(updated);
125
+ return updated;
126
+ }
127
+ /**
128
+ * Get archive configuration with defaults
129
+ */
130
+ function getArchiveConfig() {
131
+ const config = loadConfig();
132
+ return config.archive || { default: 'local' };
133
+ }
134
+ /**
135
+ * Set archive default destination
136
+ */
137
+ function setArchiveDefault(destination) {
138
+ const config = loadConfig();
139
+ config.archive = config.archive || {};
140
+ config.archive.default = destination;
141
+ saveConfig(config);
142
+ }
143
+ /**
144
+ * Set GitHub configuration
145
+ */
146
+ function setGitHubConfig(github) {
147
+ const config = loadConfig();
148
+ config.archive = config.archive || {};
149
+ config.archive.github = { ...config.archive.github, ...github };
150
+ saveConfig(config);
151
+ }
152
+ /**
153
+ * Set Linear configuration
154
+ */
155
+ function setLinearConfig(linear) {
156
+ const config = loadConfig();
157
+ config.archive = config.archive || {};
158
+ config.archive.linear = { ...config.archive.linear, ...linear };
159
+ saveConfig(config);
160
+ }
161
+ /**
162
+ * Get the effective archive destination
163
+ * Priority: brainfile.md archive.destination > config default > 'local'
164
+ *
165
+ * @param brainfileDestination - Destination from brainfile.md (if any)
166
+ * @returns The effective destination
167
+ */
168
+ function getEffectiveArchiveDestination(brainfileDestination) {
169
+ // Priority 1: brainfile.md setting
170
+ if (brainfileDestination && isValidDestination(brainfileDestination)) {
171
+ return brainfileDestination;
172
+ }
173
+ // Priority 2: config default
174
+ const config = getArchiveConfig();
175
+ if (config.default && isValidDestination(config.default)) {
176
+ return config.default;
177
+ }
178
+ // Priority 3: fallback to local
179
+ return 'local';
180
+ }
181
+ // ============================================================================
182
+ // Helper Functions
183
+ // ============================================================================
184
+ function isValidDestination(dest) {
185
+ return ['local', 'github', 'linear'].includes(dest);
186
+ }
187
+ /**
188
+ * Deep merge two objects
189
+ */
190
+ function deepMerge(target, source) {
191
+ const result = { ...target };
192
+ for (const key in source) {
193
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
194
+ const sourceValue = source[key];
195
+ const targetValue = result[key];
196
+ if (sourceValue !== null &&
197
+ typeof sourceValue === 'object' &&
198
+ !Array.isArray(sourceValue) &&
199
+ targetValue !== null &&
200
+ typeof targetValue === 'object' &&
201
+ !Array.isArray(targetValue)) {
202
+ result[key] = deepMerge(targetValue, sourceValue);
203
+ }
204
+ else {
205
+ result[key] = sourceValue;
206
+ }
207
+ }
208
+ }
209
+ return result;
210
+ }
211
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * GitHub Authentication for Brainfile CLI
3
+ *
4
+ * Supports:
5
+ * 1. Piggyback on gh CLI auth (if available)
6
+ * 2. OAuth Device Flow (browser-based, no server needed)
7
+ * 3. Personal Access Token (manual entry)
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+ /**
12
+ * Check if GitHub is already authenticated
13
+ */
14
+ export declare function isGitHubAuthenticated(): Promise<boolean>;
15
+ /**
16
+ * Get the current GitHub token (from any source)
17
+ */
18
+ export declare function getGitHubToken(): Promise<string | null>;
19
+ /**
20
+ * Authenticate with GitHub using the best available method
21
+ *
22
+ * Priority:
23
+ * 1. Use existing gh CLI auth
24
+ * 2. OAuth Device Flow
25
+ * 3. Manual PAT entry
26
+ */
27
+ export declare function authenticateGitHub(options: {
28
+ usePAT?: boolean;
29
+ token?: string;
30
+ silent?: boolean;
31
+ }): Promise<{
32
+ success: boolean;
33
+ username?: string;
34
+ error?: string;
35
+ }>;
36
+ /**
37
+ * Create a GitHub Issue
38
+ */
39
+ export declare function createGitHubIssue(options: {
40
+ owner: string;
41
+ repo: string;
42
+ title: string;
43
+ body: string;
44
+ labels?: string[];
45
+ state?: 'open' | 'closed';
46
+ }): Promise<{
47
+ success: boolean;
48
+ issueNumber?: number;
49
+ issueUrl?: string;
50
+ error?: string;
51
+ }>;
52
+ /**
53
+ * Logout from GitHub
54
+ */
55
+ export declare function logoutGitHub(): Promise<void>;
56
+ //# sourceMappingURL=github-auth.d.ts.map