@indigoai-us/hq-cli 5.1.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.
Files changed (102) hide show
  1. package/dist/__tests__/credentials.test.d.ts +5 -0
  2. package/dist/__tests__/credentials.test.d.ts.map +1 -0
  3. package/dist/__tests__/credentials.test.js +169 -0
  4. package/dist/__tests__/credentials.test.js.map +1 -0
  5. package/dist/commands/add.d.ts +6 -0
  6. package/dist/commands/add.d.ts.map +1 -0
  7. package/dist/commands/add.js +60 -0
  8. package/dist/commands/add.js.map +1 -0
  9. package/dist/commands/auth.d.ts +17 -0
  10. package/dist/commands/auth.d.ts.map +1 -0
  11. package/dist/commands/auth.js +269 -0
  12. package/dist/commands/auth.js.map +1 -0
  13. package/dist/commands/cloud-setup.d.ts +19 -0
  14. package/dist/commands/cloud-setup.d.ts.map +1 -0
  15. package/dist/commands/cloud-setup.js +206 -0
  16. package/dist/commands/cloud-setup.js.map +1 -0
  17. package/dist/commands/cloud.d.ts +16 -0
  18. package/dist/commands/cloud.d.ts.map +1 -0
  19. package/dist/commands/cloud.js +263 -0
  20. package/dist/commands/cloud.js.map +1 -0
  21. package/dist/commands/initial-upload.d.ts +67 -0
  22. package/dist/commands/initial-upload.d.ts.map +1 -0
  23. package/dist/commands/initial-upload.js +205 -0
  24. package/dist/commands/initial-upload.js.map +1 -0
  25. package/dist/commands/list.d.ts +6 -0
  26. package/dist/commands/list.d.ts.map +1 -0
  27. package/dist/commands/list.js +55 -0
  28. package/dist/commands/list.js.map +1 -0
  29. package/dist/commands/sync.d.ts +6 -0
  30. package/dist/commands/sync.d.ts.map +1 -0
  31. package/dist/commands/sync.js +104 -0
  32. package/dist/commands/sync.js.map +1 -0
  33. package/dist/commands/update.d.ts +7 -0
  34. package/dist/commands/update.d.ts.map +1 -0
  35. package/dist/commands/update.js +60 -0
  36. package/dist/commands/update.js.map +1 -0
  37. package/dist/index.d.ts +6 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +36 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/strategies/link.d.ts +7 -0
  42. package/dist/strategies/link.d.ts.map +1 -0
  43. package/dist/strategies/link.js +51 -0
  44. package/dist/strategies/link.js.map +1 -0
  45. package/dist/strategies/merge.d.ts +7 -0
  46. package/dist/strategies/merge.d.ts.map +1 -0
  47. package/dist/strategies/merge.js +110 -0
  48. package/dist/strategies/merge.js.map +1 -0
  49. package/dist/sync-worker.d.ts +11 -0
  50. package/dist/sync-worker.d.ts.map +1 -0
  51. package/dist/sync-worker.js +77 -0
  52. package/dist/sync-worker.js.map +1 -0
  53. package/dist/types.d.ts +41 -0
  54. package/dist/types.d.ts.map +1 -0
  55. package/dist/types.js +5 -0
  56. package/dist/types.js.map +1 -0
  57. package/dist/utils/api-client.d.ts +26 -0
  58. package/dist/utils/api-client.d.ts.map +1 -0
  59. package/dist/utils/api-client.js +87 -0
  60. package/dist/utils/api-client.js.map +1 -0
  61. package/dist/utils/credentials.d.ts +44 -0
  62. package/dist/utils/credentials.d.ts.map +1 -0
  63. package/dist/utils/credentials.js +101 -0
  64. package/dist/utils/credentials.js.map +1 -0
  65. package/dist/utils/git.d.ts +13 -0
  66. package/dist/utils/git.d.ts.map +1 -0
  67. package/dist/utils/git.js +70 -0
  68. package/dist/utils/git.js.map +1 -0
  69. package/dist/utils/manifest.d.ts +16 -0
  70. package/dist/utils/manifest.d.ts.map +1 -0
  71. package/dist/utils/manifest.js +95 -0
  72. package/dist/utils/manifest.js.map +1 -0
  73. package/dist/utils/sync.d.ts +125 -0
  74. package/dist/utils/sync.d.ts.map +1 -0
  75. package/dist/utils/sync.js +291 -0
  76. package/dist/utils/sync.js.map +1 -0
  77. package/package.json +36 -0
  78. package/src/__tests__/cloud-setup.test.ts +117 -0
  79. package/src/__tests__/credentials.test.ts +203 -0
  80. package/src/__tests__/initial-upload.test.ts +414 -0
  81. package/src/__tests__/sync.test.ts +627 -0
  82. package/src/commands/add.ts +74 -0
  83. package/src/commands/auth.ts +303 -0
  84. package/src/commands/cloud-setup.ts +251 -0
  85. package/src/commands/cloud.ts +300 -0
  86. package/src/commands/initial-upload.ts +263 -0
  87. package/src/commands/list.ts +66 -0
  88. package/src/commands/sync.ts +149 -0
  89. package/src/commands/update.ts +71 -0
  90. package/src/hq-cloud.d.ts +19 -0
  91. package/src/index.ts +46 -0
  92. package/src/strategies/link.ts +62 -0
  93. package/src/strategies/merge.ts +142 -0
  94. package/src/sync-worker.ts +82 -0
  95. package/src/types.ts +47 -0
  96. package/src/utils/api-client.ts +111 -0
  97. package/src/utils/credentials.ts +124 -0
  98. package/src/utils/git.ts +74 -0
  99. package/src/utils/manifest.ts +111 -0
  100. package/src/utils/sync.ts +381 -0
  101. package/tsconfig.json +9 -0
  102. package/vitest.config.ts +8 -0
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Tests for credential storage (utils/credentials.ts)
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=credentials.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/credentials.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Tests for credential storage (utils/credentials.ts)
3
+ */
4
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
5
+ import * as fs from 'fs';
6
+ import * as path from 'path';
7
+ import * as os from 'os';
8
+ import { readCredentials, writeCredentials, clearCredentials, getCredentialsPath, isExpired, _setConfigHome, } from '../utils/credentials.js';
9
+ let tmpDir;
10
+ beforeEach(() => {
11
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'hq-cli-test-'));
12
+ _setConfigHome(tmpDir);
13
+ });
14
+ afterEach(() => {
15
+ _setConfigHome(null);
16
+ try {
17
+ fs.rmSync(tmpDir, { recursive: true, force: true });
18
+ }
19
+ catch {
20
+ // Ignore cleanup errors
21
+ }
22
+ });
23
+ describe('getCredentialsPath', () => {
24
+ it('returns a path under .hq/ in the config home', () => {
25
+ const p = getCredentialsPath();
26
+ expect(p).toContain('.hq');
27
+ expect(p).toContain('credentials.json');
28
+ expect(p.startsWith(tmpDir)).toBe(true);
29
+ });
30
+ });
31
+ describe('readCredentials', () => {
32
+ it('returns null when no credentials file exists', () => {
33
+ const creds = readCredentials();
34
+ expect(creds).toBeNull();
35
+ });
36
+ it('returns null when credentials file is empty', () => {
37
+ const hqDir = path.join(tmpDir, '.hq');
38
+ fs.mkdirSync(hqDir, { recursive: true });
39
+ fs.writeFileSync(path.join(hqDir, 'credentials.json'), '');
40
+ const creds = readCredentials();
41
+ expect(creds).toBeNull();
42
+ });
43
+ it('returns null when credentials file contains invalid JSON', () => {
44
+ const hqDir = path.join(tmpDir, '.hq');
45
+ fs.mkdirSync(hqDir, { recursive: true });
46
+ fs.writeFileSync(path.join(hqDir, 'credentials.json'), 'not json');
47
+ const creds = readCredentials();
48
+ expect(creds).toBeNull();
49
+ });
50
+ it('returns null when credentials are missing required fields', () => {
51
+ const hqDir = path.join(tmpDir, '.hq');
52
+ fs.mkdirSync(hqDir, { recursive: true });
53
+ fs.writeFileSync(path.join(hqDir, 'credentials.json'), JSON.stringify({ token: 'abc' }) // missing userId
54
+ );
55
+ const creds = readCredentials();
56
+ expect(creds).toBeNull();
57
+ });
58
+ it('returns valid credentials when file is well-formed', () => {
59
+ const hqDir = path.join(tmpDir, '.hq');
60
+ fs.mkdirSync(hqDir, { recursive: true });
61
+ const stored = {
62
+ token: 'test-jwt-token',
63
+ userId: 'user_123',
64
+ email: 'test@example.com',
65
+ storedAt: new Date().toISOString(),
66
+ };
67
+ fs.writeFileSync(path.join(hqDir, 'credentials.json'), JSON.stringify(stored));
68
+ const creds = readCredentials();
69
+ expect(creds).not.toBeNull();
70
+ expect(creds.token).toBe('test-jwt-token');
71
+ expect(creds.userId).toBe('user_123');
72
+ expect(creds.email).toBe('test@example.com');
73
+ });
74
+ });
75
+ describe('writeCredentials', () => {
76
+ it('creates .hq directory and writes credentials file', () => {
77
+ const creds = {
78
+ token: 'test-token',
79
+ userId: 'user_456',
80
+ email: 'user@test.com',
81
+ storedAt: new Date().toISOString(),
82
+ };
83
+ writeCredentials(creds);
84
+ const hqDir = path.join(tmpDir, '.hq');
85
+ expect(fs.existsSync(hqDir)).toBe(true);
86
+ expect(fs.existsSync(path.join(hqDir, 'credentials.json'))).toBe(true);
87
+ const raw = fs.readFileSync(path.join(hqDir, 'credentials.json'), 'utf-8');
88
+ const parsed = JSON.parse(raw);
89
+ expect(parsed.token).toBe('test-token');
90
+ expect(parsed.userId).toBe('user_456');
91
+ });
92
+ it('overwrites existing credentials', () => {
93
+ const creds1 = {
94
+ token: 'token-1',
95
+ userId: 'user_1',
96
+ storedAt: new Date().toISOString(),
97
+ };
98
+ writeCredentials(creds1);
99
+ const creds2 = {
100
+ token: 'token-2',
101
+ userId: 'user_2',
102
+ storedAt: new Date().toISOString(),
103
+ };
104
+ writeCredentials(creds2);
105
+ const read = readCredentials();
106
+ expect(read.token).toBe('token-2');
107
+ expect(read.userId).toBe('user_2');
108
+ });
109
+ });
110
+ describe('clearCredentials', () => {
111
+ it('returns false when no credentials exist', () => {
112
+ const result = clearCredentials();
113
+ expect(result).toBe(false);
114
+ });
115
+ it('removes credentials file and returns true', () => {
116
+ writeCredentials({
117
+ token: 'test',
118
+ userId: 'user',
119
+ storedAt: new Date().toISOString(),
120
+ });
121
+ expect(readCredentials()).not.toBeNull();
122
+ const result = clearCredentials();
123
+ expect(result).toBe(true);
124
+ expect(readCredentials()).toBeNull();
125
+ });
126
+ });
127
+ describe('isExpired', () => {
128
+ it('returns false when no expiresAt is set', () => {
129
+ const creds = {
130
+ token: 'test',
131
+ userId: 'user',
132
+ storedAt: new Date().toISOString(),
133
+ };
134
+ expect(isExpired(creds)).toBe(false);
135
+ });
136
+ it('returns true when expiresAt is in the past', () => {
137
+ const creds = {
138
+ token: 'test',
139
+ userId: 'user',
140
+ storedAt: new Date().toISOString(),
141
+ expiresAt: new Date(Date.now() - 60_000).toISOString(),
142
+ };
143
+ expect(isExpired(creds)).toBe(true);
144
+ });
145
+ it('returns false when expiresAt is in the future', () => {
146
+ const creds = {
147
+ token: 'test',
148
+ userId: 'user',
149
+ storedAt: new Date().toISOString(),
150
+ expiresAt: new Date(Date.now() + 3_600_000).toISOString(),
151
+ };
152
+ expect(isExpired(creds)).toBe(false);
153
+ });
154
+ });
155
+ describe('roundtrip', () => {
156
+ it('write then read returns identical data', () => {
157
+ const original = {
158
+ token: 'jwt-abc-123',
159
+ userId: 'user_roundtrip',
160
+ email: 'roundtrip@test.com',
161
+ storedAt: '2026-01-15T10:00:00.000Z',
162
+ expiresAt: '2026-01-15T11:00:00.000Z',
163
+ };
164
+ writeCredentials(original);
165
+ const read = readCredentials();
166
+ expect(read).toEqual(original);
167
+ });
168
+ });
169
+ //# sourceMappingURL=credentials.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.test.js","sourceRoot":"","sources":["../../src/__tests__/credentials.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * hq modules add command (US-003)
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function registerAddCommand(program: Command): void;
6
+ //# sourceMappingURL=add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiEzD"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * hq modules add command (US-003)
3
+ */
4
+ import { findHqRoot, addModule, parseRepoName, isValidRepoUrl } from '../utils/manifest.js';
5
+ export function registerAddCommand(program) {
6
+ program
7
+ .command('add <repo-url>')
8
+ .description('Add a module to the manifest')
9
+ .option('--as <name>', 'Module name (defaults to repo name)')
10
+ .option('--branch <branch>', 'Git branch to track', 'main')
11
+ .option('--strategy <strategy>', 'Sync strategy: link | merge | copy', 'link')
12
+ .option('--path <mapping>', 'Path mapping src:dest (can repeat)', (val, prev) => [...prev, val], [])
13
+ .action(async (repoUrl, options) => {
14
+ try {
15
+ // Validate repo URL
16
+ if (!isValidRepoUrl(repoUrl)) {
17
+ console.error('Error: Invalid repo URL. Must start with https:// or git@');
18
+ process.exit(1);
19
+ }
20
+ // Parse name
21
+ const name = options.as || parseRepoName(repoUrl);
22
+ // Validate strategy
23
+ const validStrategies = ['link', 'merge', 'copy'];
24
+ if (!validStrategies.includes(options.strategy)) {
25
+ console.error(`Error: Invalid strategy "${options.strategy}". Use: ${validStrategies.join(', ')}`);
26
+ process.exit(1);
27
+ }
28
+ // Parse path mappings
29
+ const paths = options.path.length > 0
30
+ ? options.path.map(p => {
31
+ const [src, dest] = p.split(':');
32
+ if (!src || !dest) {
33
+ throw new Error(`Invalid path mapping: ${p}. Format: src:dest`);
34
+ }
35
+ return { src, dest };
36
+ })
37
+ : [{ src: '.', dest: `workers/${name}` }]; // Default: entire repo to workers/
38
+ const module = {
39
+ name,
40
+ repo: repoUrl,
41
+ branch: options.branch,
42
+ strategy: options.strategy,
43
+ paths,
44
+ };
45
+ const hqRoot = findHqRoot();
46
+ addModule(hqRoot, module);
47
+ console.log(`Added module "${name}"`);
48
+ console.log(` Repo: ${repoUrl}`);
49
+ console.log(` Branch: ${options.branch}`);
50
+ console.log(` Strategy: ${options.strategy}`);
51
+ console.log(` Paths: ${paths.map(p => `${p.src} -> ${p.dest}`).join(', ')}`);
52
+ console.log('\nRun "hq modules sync" to fetch and sync the module.');
53
+ }
54
+ catch (error) {
55
+ console.error('Error:', error instanceof Error ? error.message : error);
56
+ process.exit(1);
57
+ }
58
+ });
59
+ }
60
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * hq auth commands — login, logout, status
3
+ *
4
+ * Login flow:
5
+ * 1. CLI generates a unique device code
6
+ * 2. CLI starts a temporary localhost HTTP server to receive the callback
7
+ * 3. CLI opens the user's browser to the hq-cloud API auth page with the device code + callback port
8
+ * 4. User signs in with Clerk in the browser
9
+ * 5. After sign-in, the API redirects to the localhost callback with the token
10
+ * 6. CLI captures the token, stores it, and shuts down the server
11
+ */
12
+ import { Command } from 'commander';
13
+ /**
14
+ * Register the "hq auth" command group with login, logout, and status subcommands.
15
+ */
16
+ export declare function registerAuthCommand(program: Command): void;
17
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0KpC;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAqH1D"}
@@ -0,0 +1,269 @@
1
+ /**
2
+ * hq auth commands — login, logout, status
3
+ *
4
+ * Login flow:
5
+ * 1. CLI generates a unique device code
6
+ * 2. CLI starts a temporary localhost HTTP server to receive the callback
7
+ * 3. CLI opens the user's browser to the hq-cloud API auth page with the device code + callback port
8
+ * 4. User signs in with Clerk in the browser
9
+ * 5. After sign-in, the API redirects to the localhost callback with the token
10
+ * 6. CLI captures the token, stores it, and shuts down the server
11
+ */
12
+ import * as http from 'http';
13
+ import * as crypto from 'crypto';
14
+ import chalk from 'chalk';
15
+ import { readCredentials, writeCredentials, clearCredentials, getCredentialsPath, isExpired, } from '../utils/credentials.js';
16
+ import { getApiUrl, apiRequest } from '../utils/api-client.js';
17
+ /** Port range for the localhost callback server */
18
+ const MIN_PORT = 19750;
19
+ const MAX_PORT = 19850;
20
+ /** Timeout for waiting for the browser callback (ms) */
21
+ const LOGIN_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
22
+ /**
23
+ * Open a URL in the user's default browser.
24
+ * Works on macOS, Linux, and Windows.
25
+ */
26
+ async function openBrowser(url) {
27
+ const { exec } = await import('child_process');
28
+ const { promisify } = await import('util');
29
+ const execAsync = promisify(exec);
30
+ const platform = process.platform;
31
+ let command;
32
+ if (platform === 'darwin') {
33
+ command = `open "${url}"`;
34
+ }
35
+ else if (platform === 'win32') {
36
+ command = `start "" "${url}"`;
37
+ }
38
+ else {
39
+ // Linux — try xdg-open, then sensible-browser
40
+ command = `xdg-open "${url}" 2>/dev/null || sensible-browser "${url}" 2>/dev/null || echo "OPEN_FAILED"`;
41
+ }
42
+ try {
43
+ await execAsync(command);
44
+ }
45
+ catch {
46
+ // Browser open failed silently — user will be shown the URL to open manually
47
+ }
48
+ }
49
+ /**
50
+ * Find an available port in the callback port range.
51
+ */
52
+ function findAvailablePort() {
53
+ return new Promise((resolve, reject) => {
54
+ const port = MIN_PORT + Math.floor(Math.random() * (MAX_PORT - MIN_PORT));
55
+ const server = http.createServer();
56
+ server.listen(port, '127.0.0.1', () => {
57
+ server.close(() => resolve(port));
58
+ });
59
+ server.on('error', () => {
60
+ // Try another port
61
+ const fallback = MIN_PORT + Math.floor(Math.random() * (MAX_PORT - MIN_PORT));
62
+ const server2 = http.createServer();
63
+ server2.listen(fallback, '127.0.0.1', () => {
64
+ server2.close(() => resolve(fallback));
65
+ });
66
+ server2.on('error', () => {
67
+ reject(new Error('Could not find an available port for auth callback'));
68
+ });
69
+ });
70
+ });
71
+ }
72
+ /**
73
+ * HTML page shown to the user after successful login.
74
+ */
75
+ function successHtml() {
76
+ return `<!DOCTYPE html>
77
+ <html>
78
+ <head><title>HQ CLI — Logged In</title></head>
79
+ <body style="font-family: system-ui, sans-serif; display: flex; align-items: center; justify-content: center; height: 100vh; margin: 0; background: #f8f9fa;">
80
+ <div style="text-align: center; max-width: 400px;">
81
+ <h1 style="color: #16a34a;">Logged In</h1>
82
+ <p style="color: #4b5563;">You have been authenticated. You can close this tab and return to the terminal.</p>
83
+ </div>
84
+ </body>
85
+ </html>`;
86
+ }
87
+ /**
88
+ * HTML page shown on error.
89
+ */
90
+ function errorHtml(message) {
91
+ return `<!DOCTYPE html>
92
+ <html>
93
+ <head><title>HQ CLI — Auth Error</title></head>
94
+ <body style="font-family: system-ui, sans-serif; display: flex; align-items: center; justify-content: center; height: 100vh; margin: 0; background: #f8f9fa;">
95
+ <div style="text-align: center; max-width: 400px;">
96
+ <h1 style="color: #dc2626;">Authentication Error</h1>
97
+ <p style="color: #4b5563;">${message}</p>
98
+ <p style="color: #6b7280;">Please return to the terminal and try again.</p>
99
+ </div>
100
+ </body>
101
+ </html>`;
102
+ }
103
+ /**
104
+ * Start a temporary localhost server and wait for the auth callback.
105
+ * Returns the received token and user info.
106
+ */
107
+ function waitForCallback(port) {
108
+ return new Promise((resolve, reject) => {
109
+ const server = http.createServer((req, res) => {
110
+ const url = new URL(req.url ?? '/', `http://127.0.0.1:${port}`);
111
+ if (url.pathname === '/callback') {
112
+ const token = url.searchParams.get('token');
113
+ const userId = url.searchParams.get('user_id');
114
+ const email = url.searchParams.get('email') ?? undefined;
115
+ const expiresAt = url.searchParams.get('expires_at') ?? undefined;
116
+ const error = url.searchParams.get('error');
117
+ if (error) {
118
+ res.writeHead(200, { 'Content-Type': 'text/html' });
119
+ res.end(errorHtml(error));
120
+ server.close();
121
+ reject(new Error(error));
122
+ return;
123
+ }
124
+ if (!token || !userId) {
125
+ res.writeHead(200, { 'Content-Type': 'text/html' });
126
+ res.end(errorHtml('Missing token or user ID in callback'));
127
+ server.close();
128
+ reject(new Error('Invalid callback: missing token or user_id'));
129
+ return;
130
+ }
131
+ res.writeHead(200, { 'Content-Type': 'text/html' });
132
+ res.end(successHtml());
133
+ // Close the server after sending the response
134
+ server.close();
135
+ resolve({ token, userId, email, expiresAt });
136
+ }
137
+ else {
138
+ res.writeHead(404, { 'Content-Type': 'text/plain' });
139
+ res.end('Not Found');
140
+ }
141
+ });
142
+ server.listen(port, '127.0.0.1', () => {
143
+ // Server is ready
144
+ });
145
+ // Timeout
146
+ const timeout = setTimeout(() => {
147
+ server.close();
148
+ reject(new Error('Login timed out. Please try again.'));
149
+ }, LOGIN_TIMEOUT_MS);
150
+ server.on('close', () => {
151
+ clearTimeout(timeout);
152
+ });
153
+ server.on('error', (err) => {
154
+ clearTimeout(timeout);
155
+ reject(err);
156
+ });
157
+ });
158
+ }
159
+ /**
160
+ * Register the "hq auth" command group with login, logout, and status subcommands.
161
+ */
162
+ export function registerAuthCommand(program) {
163
+ const authCmd = program
164
+ .command('auth')
165
+ .description('Authenticate with HQ Cloud');
166
+ // --- hq auth login ---
167
+ authCmd
168
+ .command('login')
169
+ .description('Log in to HQ Cloud via browser')
170
+ .action(async () => {
171
+ try {
172
+ // Check if already logged in
173
+ const existing = readCredentials();
174
+ if (existing && !isExpired(existing)) {
175
+ const label = existing.email ?? existing.userId;
176
+ console.log(chalk.yellow(`Already logged in as ${label}.`));
177
+ console.log('Run "hq auth logout" first to switch accounts.');
178
+ return;
179
+ }
180
+ // Generate a device code for the login session
181
+ const deviceCode = crypto.randomBytes(16).toString('hex');
182
+ // Find an available port for the callback
183
+ const port = await findAvailablePort();
184
+ const callbackUrl = `http://127.0.0.1:${port}/callback`;
185
+ // Build the login URL
186
+ const apiUrl = getApiUrl();
187
+ const loginUrl = `${apiUrl}/auth/cli-login?device_code=${deviceCode}&callback_url=${encodeURIComponent(callbackUrl)}`;
188
+ console.log(chalk.blue('Opening browser for authentication...'));
189
+ console.log();
190
+ console.log(`If the browser does not open, visit this URL:`);
191
+ console.log(chalk.underline(loginUrl));
192
+ console.log();
193
+ console.log(chalk.dim('Waiting for authentication (timeout: 5 minutes)...'));
194
+ // Open browser
195
+ await openBrowser(loginUrl);
196
+ // Wait for callback
197
+ const result = await waitForCallback(port);
198
+ // Store credentials
199
+ writeCredentials({
200
+ token: result.token,
201
+ userId: result.userId,
202
+ email: result.email,
203
+ storedAt: new Date().toISOString(),
204
+ expiresAt: result.expiresAt,
205
+ });
206
+ const label = result.email ?? result.userId;
207
+ console.log();
208
+ console.log(chalk.green(`Logged in as ${label}`));
209
+ console.log(chalk.dim(`Credentials saved to ${getCredentialsPath()}`));
210
+ }
211
+ catch (error) {
212
+ console.error(chalk.red('Login failed:'), error instanceof Error ? error.message : error);
213
+ process.exit(1);
214
+ }
215
+ });
216
+ // --- hq auth logout ---
217
+ authCmd
218
+ .command('logout')
219
+ .description('Log out and clear stored credentials')
220
+ .action(() => {
221
+ const removed = clearCredentials();
222
+ if (removed) {
223
+ console.log(chalk.green('Logged out. Credentials cleared.'));
224
+ }
225
+ else {
226
+ console.log(chalk.yellow('Not logged in.'));
227
+ }
228
+ });
229
+ // --- hq auth status ---
230
+ authCmd
231
+ .command('status')
232
+ .description('Show current authentication status')
233
+ .action(async () => {
234
+ const creds = readCredentials();
235
+ if (!creds) {
236
+ console.log(chalk.yellow('Not logged in.'));
237
+ console.log('Run "hq auth login" to authenticate.');
238
+ return;
239
+ }
240
+ if (isExpired(creds)) {
241
+ console.log(chalk.red('Session expired.'));
242
+ console.log('Run "hq auth login" to re-authenticate.');
243
+ return;
244
+ }
245
+ const label = creds.email ?? creds.userId;
246
+ console.log(chalk.green(`Logged in as ${label}`));
247
+ console.log(` User ID: ${creds.userId}`);
248
+ console.log(` Stored at: ${creds.storedAt}`);
249
+ if (creds.expiresAt) {
250
+ console.log(` Expires at: ${creds.expiresAt}`);
251
+ }
252
+ console.log(` API URL: ${getApiUrl()}`);
253
+ console.log(` Creds file: ${getCredentialsPath()}`);
254
+ // Optionally verify with the API
255
+ try {
256
+ const resp = await apiRequest('GET', '/auth/me');
257
+ if (resp.ok && resp.data) {
258
+ console.log(chalk.dim(` Verified: API confirms session is valid`));
259
+ }
260
+ else {
261
+ console.log(chalk.yellow(` Warning: API returned ${resp.status} — token may be invalid`));
262
+ }
263
+ }
264
+ catch {
265
+ console.log(chalk.dim(` Note: Could not reach API to verify token`));
266
+ }
267
+ });
268
+ }
269
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * hq cloud commands — cloud session management
3
+ *
4
+ * Subcommands:
5
+ * - setup-token: Walk user through generating and storing a Claude OAuth token
6
+ * - status: Show cloud readiness (auth state + Claude token state)
7
+ * - upload: Initial HQ file upload to cloud storage
8
+ */
9
+ import { Command } from 'commander';
10
+ /**
11
+ * Validate a Claude OAuth token string.
12
+ * Returns null if valid, or an error message string if invalid.
13
+ */
14
+ export declare function validateClaudeToken(token: string): string | null;
15
+ /**
16
+ * Register the "hq cloud" command group with setup-token and status subcommands.
17
+ */
18
+ export declare function registerCloudSetupCommand(program: Command): void;
19
+ //# sourceMappingURL=cloud-setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-setup.d.ts","sourceRoot":"","sources":["../../src/commands/cloud-setup.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBhE;AAoBD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuLhE"}