@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.
- package/dist/__tests__/credentials.test.d.ts +5 -0
- package/dist/__tests__/credentials.test.d.ts.map +1 -0
- package/dist/__tests__/credentials.test.js +169 -0
- package/dist/__tests__/credentials.test.js.map +1 -0
- package/dist/commands/add.d.ts +6 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +60 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/auth.d.ts +17 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +269 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/cloud-setup.d.ts +19 -0
- package/dist/commands/cloud-setup.d.ts.map +1 -0
- package/dist/commands/cloud-setup.js +206 -0
- package/dist/commands/cloud-setup.js.map +1 -0
- package/dist/commands/cloud.d.ts +16 -0
- package/dist/commands/cloud.d.ts.map +1 -0
- package/dist/commands/cloud.js +263 -0
- package/dist/commands/cloud.js.map +1 -0
- package/dist/commands/initial-upload.d.ts +67 -0
- package/dist/commands/initial-upload.d.ts.map +1 -0
- package/dist/commands/initial-upload.js +205 -0
- package/dist/commands/initial-upload.js.map +1 -0
- package/dist/commands/list.d.ts +6 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +55 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/sync.d.ts +6 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +104 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/update.d.ts +7 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +60 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/strategies/link.d.ts +7 -0
- package/dist/strategies/link.d.ts.map +1 -0
- package/dist/strategies/link.js +51 -0
- package/dist/strategies/link.js.map +1 -0
- package/dist/strategies/merge.d.ts +7 -0
- package/dist/strategies/merge.d.ts.map +1 -0
- package/dist/strategies/merge.js +110 -0
- package/dist/strategies/merge.js.map +1 -0
- package/dist/sync-worker.d.ts +11 -0
- package/dist/sync-worker.d.ts.map +1 -0
- package/dist/sync-worker.js +77 -0
- package/dist/sync-worker.js.map +1 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/api-client.d.ts +26 -0
- package/dist/utils/api-client.d.ts.map +1 -0
- package/dist/utils/api-client.js +87 -0
- package/dist/utils/api-client.js.map +1 -0
- package/dist/utils/credentials.d.ts +44 -0
- package/dist/utils/credentials.d.ts.map +1 -0
- package/dist/utils/credentials.js +101 -0
- package/dist/utils/credentials.js.map +1 -0
- package/dist/utils/git.d.ts +13 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +70 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/manifest.d.ts +16 -0
- package/dist/utils/manifest.d.ts.map +1 -0
- package/dist/utils/manifest.js +95 -0
- package/dist/utils/manifest.js.map +1 -0
- package/dist/utils/sync.d.ts +125 -0
- package/dist/utils/sync.d.ts.map +1 -0
- package/dist/utils/sync.js +291 -0
- package/dist/utils/sync.js.map +1 -0
- package/package.json +36 -0
- package/src/__tests__/cloud-setup.test.ts +117 -0
- package/src/__tests__/credentials.test.ts +203 -0
- package/src/__tests__/initial-upload.test.ts +414 -0
- package/src/__tests__/sync.test.ts +627 -0
- package/src/commands/add.ts +74 -0
- package/src/commands/auth.ts +303 -0
- package/src/commands/cloud-setup.ts +251 -0
- package/src/commands/cloud.ts +300 -0
- package/src/commands/initial-upload.ts +263 -0
- package/src/commands/list.ts +66 -0
- package/src/commands/sync.ts +149 -0
- package/src/commands/update.ts +71 -0
- package/src/hq-cloud.d.ts +19 -0
- package/src/index.ts +46 -0
- package/src/strategies/link.ts +62 -0
- package/src/strategies/merge.ts +142 -0
- package/src/sync-worker.ts +82 -0
- package/src/types.ts +47 -0
- package/src/utils/api-client.ts +111 -0
- package/src/utils/credentials.ts +124 -0
- package/src/utils/git.ts +74 -0
- package/src/utils/manifest.ts +111 -0
- package/src/utils/sync.ts +381 -0
- package/tsconfig.json +9 -0
- package/vitest.config.ts +8 -0
|
@@ -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 @@
|
|
|
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"}
|