@indigoai-us/hq-cli 5.3.1 → 5.4.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/bin/hq-auth-refresh.d.ts +13 -0
- package/dist/bin/hq-auth-refresh.d.ts.map +1 -0
- package/dist/bin/hq-auth-refresh.js +27 -0
- package/dist/bin/hq-auth-refresh.js.map +1 -0
- package/dist/commands/auth.d.ts +17 -13
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +83 -238
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/cloud.d.ts +3 -12
- package/dist/commands/cloud.d.ts.map +1 -1
- package/dist/commands/cloud.js +55 -212
- package/dist/commands/cloud.js.map +1 -1
- package/dist/commands/login.d.ts +6 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +25 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +6 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +21 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/onboard.d.ts +23 -0
- package/dist/commands/onboard.d.ts.map +1 -0
- package/dist/commands/onboard.js +142 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/pkg-install.d.ts +17 -0
- package/dist/commands/pkg-install.d.ts.map +1 -0
- package/dist/commands/pkg-install.js +144 -0
- package/dist/commands/pkg-install.js.map +1 -0
- package/dist/commands/pkg-list.d.ts +8 -0
- package/dist/commands/pkg-list.d.ts.map +1 -0
- package/dist/commands/pkg-list.js +70 -0
- package/dist/commands/pkg-list.js.map +1 -0
- package/dist/commands/pkg-remove.d.ts +10 -0
- package/dist/commands/pkg-remove.d.ts.map +1 -0
- package/dist/commands/pkg-remove.js +53 -0
- package/dist/commands/pkg-remove.js.map +1 -0
- package/dist/commands/pkg-update.d.ts +9 -0
- package/dist/commands/pkg-update.d.ts.map +1 -0
- package/dist/commands/pkg-update.js +124 -0
- package/dist/commands/pkg-update.js.map +1 -0
- package/dist/commands/team-sync.d.ts +14 -0
- package/dist/commands/team-sync.d.ts.map +1 -0
- package/dist/commands/team-sync.js +422 -0
- package/dist/commands/team-sync.js.map +1 -0
- package/dist/commands/whoami.d.ts +6 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +29 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +33 -13
- package/dist/index.js.map +1 -1
- package/dist/strategies/merge.js +2 -2
- package/dist/strategies/merge.js.map +1 -1
- package/dist/utils/auth.d.ts +27 -0
- package/dist/utils/auth.d.ts.map +1 -0
- package/dist/utils/auth.js +155 -0
- package/dist/utils/auth.js.map +1 -0
- package/dist/utils/cognito-session.d.ts +35 -0
- package/dist/utils/cognito-session.d.ts.map +1 -0
- package/dist/utils/cognito-session.js +72 -0
- package/dist/utils/cognito-session.js.map +1 -0
- package/dist/utils/git.js +1 -1
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/hq-root.d.ts +10 -0
- package/dist/utils/hq-root.d.ts.map +1 -0
- package/dist/utils/hq-root.js +22 -0
- package/dist/utils/hq-root.js.map +1 -0
- package/dist/utils/integrity.d.ts +14 -0
- package/dist/utils/integrity.d.ts.map +1 -0
- package/dist/utils/integrity.js +40 -0
- package/dist/utils/integrity.js.map +1 -0
- package/dist/utils/manifest.d.ts.map +1 -1
- package/dist/utils/manifest.js +2 -5
- package/dist/utils/manifest.js.map +1 -1
- package/dist/utils/registry-client.d.ts +65 -0
- package/dist/utils/registry-client.d.ts.map +1 -0
- package/dist/utils/registry-client.js +102 -0
- package/dist/utils/registry-client.js.map +1 -0
- package/dist/utils/registry.d.ts +33 -0
- package/dist/utils/registry.d.ts.map +1 -0
- package/dist/utils/registry.js +58 -0
- package/dist/utils/registry.js.map +1 -0
- package/dist/utils/token-store.d.ts +28 -0
- package/dist/utils/token-store.d.ts.map +1 -0
- package/dist/utils/token-store.js +68 -0
- package/dist/utils/token-store.js.map +1 -0
- package/package.json +35 -45
- package/src/bin/hq-auth-refresh.ts +32 -0
- package/src/commands/add.ts +74 -0
- package/src/commands/auth.ts +153 -0
- package/src/commands/cloud.ts +125 -0
- package/src/commands/list.ts +66 -0
- package/src/commands/login.ts +29 -0
- package/src/commands/logout.ts +25 -0
- package/src/commands/pkg-install.ts +181 -0
- package/src/commands/pkg-list.ts +98 -0
- package/src/commands/pkg-remove.ts +71 -0
- package/src/commands/pkg-update.ts +189 -0
- package/src/commands/sync.ts +149 -0
- package/src/commands/team-sync.ts +629 -0
- package/src/commands/update.ts +71 -0
- package/src/commands/whoami.ts +38 -0
- package/src/index.ts +72 -0
- package/src/schemas/hq-package.schema.json +137 -0
- package/src/strategies/link.ts +62 -0
- package/src/strategies/merge.ts +142 -0
- package/src/types.ts +47 -0
- package/src/utils/auth.ts +193 -0
- package/src/utils/cognito-session.ts +94 -0
- package/src/utils/git.ts +74 -0
- package/src/utils/hq-root.ts +27 -0
- package/src/utils/integrity.ts +54 -0
- package/src/utils/manifest.ts +109 -0
- package/src/utils/registry-client.ts +204 -0
- package/src/utils/registry.ts +89 -0
- package/src/utils/token-store.ts +83 -0
- package/tsconfig.json +8 -0
- package/dist/commands/cloud-setup.d.ts +0 -19
- package/dist/commands/cloud-setup.d.ts.map +0 -1
- package/dist/commands/cloud-setup.js +0 -206
- package/dist/commands/cloud-setup.js.map +0 -1
- package/dist/commands/initial-upload.d.ts +0 -67
- package/dist/commands/initial-upload.d.ts.map +0 -1
- package/dist/commands/initial-upload.js +0 -205
- package/dist/commands/initial-upload.js.map +0 -1
- package/dist/sync-worker.d.ts +0 -11
- package/dist/sync-worker.d.ts.map +0 -1
- package/dist/sync-worker.js +0 -77
- package/dist/sync-worker.js.map +0 -1
- package/dist/utils/api-client.d.ts +0 -26
- package/dist/utils/api-client.d.ts.map +0 -1
- package/dist/utils/api-client.js +0 -87
- package/dist/utils/api-client.js.map +0 -1
- package/dist/utils/credentials.d.ts +0 -44
- package/dist/utils/credentials.d.ts.map +0 -1
- package/dist/utils/credentials.js +0 -101
- package/dist/utils/credentials.js.map +0 -1
- package/dist/utils/sync.d.ts +0 -125
- package/dist/utils/sync.d.ts.map +0 -1
- package/dist/utils/sync.js +0 -291
- package/dist/utils/sync.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAgClD;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,SAAS,CAAC,CA6FpB;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,SAAS,CAAC,CAkCvD"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth utilities — OAuth PKCE flow for Clerk (US-004)
|
|
3
|
+
*
|
|
4
|
+
* Token values are NEVER written to stdout or logs.
|
|
5
|
+
*/
|
|
6
|
+
import * as crypto from 'crypto';
|
|
7
|
+
import * as http from 'http';
|
|
8
|
+
import { exec } from 'child_process';
|
|
9
|
+
import { saveToken, loadToken, isTokenExpired } from './token-store.js';
|
|
10
|
+
import { getRegistryUrl } from './registry-client.js';
|
|
11
|
+
/**
|
|
12
|
+
* Generate a cryptographically random PKCE code verifier (43-128 chars, URL-safe).
|
|
13
|
+
*/
|
|
14
|
+
function generateCodeVerifier() {
|
|
15
|
+
return crypto.randomBytes(32).toString('base64url');
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Derive the PKCE code challenge from the verifier (S256).
|
|
19
|
+
*/
|
|
20
|
+
function generateCodeChallenge(verifier) {
|
|
21
|
+
return crypto.createHash('sha256').update(verifier).digest('base64url');
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Open a URL in the default browser (macOS / Linux).
|
|
25
|
+
*/
|
|
26
|
+
function openBrowser(url) {
|
|
27
|
+
const command = process.platform === 'darwin' ? `open "${url}"` : `xdg-open "${url}"`;
|
|
28
|
+
exec(command, (err) => {
|
|
29
|
+
if (err) {
|
|
30
|
+
// Non-fatal — user can manually open the URL
|
|
31
|
+
console.error(`Could not open browser automatically. Please visit:\n ${url}`);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Start the OAuth PKCE auth flow:
|
|
37
|
+
* 1. Generate PKCE code_verifier + code_challenge
|
|
38
|
+
* 2. Start local HTTP server on a random port for the callback
|
|
39
|
+
* 3. Open browser to Clerk auth URL
|
|
40
|
+
* 4. Wait for callback with auth code
|
|
41
|
+
* 5. Exchange code for token via registry /auth/token endpoint
|
|
42
|
+
* 6. Return AuthToken
|
|
43
|
+
*/
|
|
44
|
+
export async function startAuthFlow(registryUrl) {
|
|
45
|
+
const codeVerifier = generateCodeVerifier();
|
|
46
|
+
const codeChallenge = generateCodeChallenge(codeVerifier);
|
|
47
|
+
return new Promise((resolve, reject) => {
|
|
48
|
+
const server = http.createServer(async (req, res) => {
|
|
49
|
+
try {
|
|
50
|
+
const url = new URL(req.url ?? '/', `http://localhost`);
|
|
51
|
+
if (url.pathname !== '/callback') {
|
|
52
|
+
res.writeHead(404);
|
|
53
|
+
res.end('Not found');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const code = url.searchParams.get('code');
|
|
57
|
+
const error = url.searchParams.get('error');
|
|
58
|
+
if (error) {
|
|
59
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
60
|
+
res.end('<html><body><h2>Authentication failed</h2><p>You can close this window.</p></body></html>');
|
|
61
|
+
server.close();
|
|
62
|
+
reject(new Error(`Auth failed: ${error}`));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (!code) {
|
|
66
|
+
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
67
|
+
res.end('<html><body><h2>Missing auth code</h2><p>You can close this window.</p></body></html>');
|
|
68
|
+
server.close();
|
|
69
|
+
reject(new Error('No authorization code received'));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
// Exchange code for token
|
|
73
|
+
const tokenResponse = await fetch(`${registryUrl}/auth/token`, {
|
|
74
|
+
method: 'POST',
|
|
75
|
+
headers: { 'Content-Type': 'application/json' },
|
|
76
|
+
body: JSON.stringify({
|
|
77
|
+
code,
|
|
78
|
+
code_verifier: codeVerifier,
|
|
79
|
+
redirect_uri: `http://localhost:${server.address().port}/callback`,
|
|
80
|
+
}),
|
|
81
|
+
});
|
|
82
|
+
if (!tokenResponse.ok) {
|
|
83
|
+
const body = await tokenResponse.text();
|
|
84
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
85
|
+
res.end('<html><body><h2>Token exchange failed</h2><p>You can close this window.</p></body></html>');
|
|
86
|
+
server.close();
|
|
87
|
+
reject(new Error(`Token exchange failed (${tokenResponse.status}): ${body}`));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const tokenData = (await tokenResponse.json());
|
|
91
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
92
|
+
res.end('<html><body><h2>Authenticated!</h2><p>You can close this window and return to the terminal.</p></body></html>');
|
|
93
|
+
server.close();
|
|
94
|
+
resolve(tokenData);
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
server.close();
|
|
98
|
+
reject(err);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
// Listen on random port
|
|
102
|
+
server.listen(0, '127.0.0.1', () => {
|
|
103
|
+
const addr = server.address();
|
|
104
|
+
const redirectUri = `http://localhost:${addr.port}/callback`;
|
|
105
|
+
const authUrl = `${registryUrl}/auth/login?redirect_uri=${encodeURIComponent(redirectUri)}&code_challenge=${codeChallenge}&code_challenge_method=S256`;
|
|
106
|
+
console.log('Opening browser for authentication...');
|
|
107
|
+
openBrowser(authUrl);
|
|
108
|
+
console.log(`\nIf the browser doesn't open, visit:\n ${authUrl}\n`);
|
|
109
|
+
});
|
|
110
|
+
// Timeout after 2 minutes
|
|
111
|
+
setTimeout(() => {
|
|
112
|
+
server.close();
|
|
113
|
+
reject(new Error('Authentication timed out after 2 minutes'));
|
|
114
|
+
}, 120_000);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get a valid auth token:
|
|
119
|
+
* 1. Load from store
|
|
120
|
+
* 2. If expired or within 5 min buffer: try refresh
|
|
121
|
+
* 3. If refresh fails: throw with message to re-login
|
|
122
|
+
* 4. Return valid token
|
|
123
|
+
*
|
|
124
|
+
* Token values are NEVER written to stdout.
|
|
125
|
+
*/
|
|
126
|
+
export async function getAuthToken() {
|
|
127
|
+
const token = await loadToken();
|
|
128
|
+
if (!token) {
|
|
129
|
+
throw new Error("Not logged in. Run 'hq login' to authenticate.");
|
|
130
|
+
}
|
|
131
|
+
if (!isTokenExpired(token)) {
|
|
132
|
+
return token;
|
|
133
|
+
}
|
|
134
|
+
// Attempt refresh
|
|
135
|
+
try {
|
|
136
|
+
const registryUrl = getRegistryUrl();
|
|
137
|
+
const refreshResponse = await fetch(`${registryUrl}/auth/refresh`, {
|
|
138
|
+
method: 'POST',
|
|
139
|
+
headers: { 'Content-Type': 'application/json' },
|
|
140
|
+
body: JSON.stringify({
|
|
141
|
+
clerk_session_token: token.clerk_session_token,
|
|
142
|
+
}),
|
|
143
|
+
});
|
|
144
|
+
if (refreshResponse.ok) {
|
|
145
|
+
const refreshedToken = (await refreshResponse.json());
|
|
146
|
+
await saveToken(refreshedToken);
|
|
147
|
+
return refreshedToken;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// Refresh failed — fall through to error
|
|
152
|
+
}
|
|
153
|
+
throw new Error("Session expired. Run 'hq login' to re-authenticate.");
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Cognito session helpers for hq-cli commands.
|
|
3
|
+
*
|
|
4
|
+
* Consumed by `hq auth refresh` and the standalone `hq-auth-refresh` bin
|
|
5
|
+
* invoked by the deploy skill (.claude/skills/deploy/SKILL.md step 4).
|
|
6
|
+
*
|
|
7
|
+
* Defaults point at the shared hq-vault-dev Cognito pool. Override via env:
|
|
8
|
+
*
|
|
9
|
+
* AWS_REGION — e.g. us-east-1
|
|
10
|
+
* HQ_COGNITO_DOMAIN — Cognito User Pool domain prefix
|
|
11
|
+
* HQ_COGNITO_CLIENT_ID — App Client ID
|
|
12
|
+
* HQ_COGNITO_CALLBACK_PORT — Loopback OAuth callback port
|
|
13
|
+
*/
|
|
14
|
+
import { type CognitoAuthConfig } from "@indigoai-us/hq-cloud";
|
|
15
|
+
export declare const DEFAULT_COGNITO: CognitoAuthConfig;
|
|
16
|
+
/**
|
|
17
|
+
* Return a non-expired Cognito access token, refreshing or browser-logging-in
|
|
18
|
+
* as needed. Cache lives at ~/.hq/cognito-tokens.json.
|
|
19
|
+
*
|
|
20
|
+
* Pass `interactive: false` from automated contexts where failing fast is
|
|
21
|
+
* better than opening a browser.
|
|
22
|
+
*/
|
|
23
|
+
export declare function ensureCognitoToken(options?: {
|
|
24
|
+
interactive?: boolean;
|
|
25
|
+
}): Promise<string>;
|
|
26
|
+
/**
|
|
27
|
+
* Refresh the cached Cognito session once and return the result. Used by
|
|
28
|
+
* `hq auth refresh` and the `hq-auth-refresh` bin. Never opens a browser —
|
|
29
|
+
* if no cached tokens exist or the refresh fails, throws.
|
|
30
|
+
*/
|
|
31
|
+
export declare function refreshCachedSession(): Promise<{
|
|
32
|
+
refreshed: boolean;
|
|
33
|
+
reason?: string;
|
|
34
|
+
}>;
|
|
35
|
+
//# sourceMappingURL=cognito-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cognito-session.d.ts","sourceRoot":"","sources":["../../src/utils/cognito-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAKL,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAE/B,eAAO,MAAM,eAAe,EAAE,iBAQ7B,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,GAAE;IAChD,WAAW,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BvB;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC;IACpD,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC,CAcD"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Cognito session helpers for hq-cli commands.
|
|
3
|
+
*
|
|
4
|
+
* Consumed by `hq auth refresh` and the standalone `hq-auth-refresh` bin
|
|
5
|
+
* invoked by the deploy skill (.claude/skills/deploy/SKILL.md step 4).
|
|
6
|
+
*
|
|
7
|
+
* Defaults point at the shared hq-vault-dev Cognito pool. Override via env:
|
|
8
|
+
*
|
|
9
|
+
* AWS_REGION — e.g. us-east-1
|
|
10
|
+
* HQ_COGNITO_DOMAIN — Cognito User Pool domain prefix
|
|
11
|
+
* HQ_COGNITO_CLIENT_ID — App Client ID
|
|
12
|
+
* HQ_COGNITO_CALLBACK_PORT — Loopback OAuth callback port
|
|
13
|
+
*/
|
|
14
|
+
import { loadCachedTokens, isExpiring, refreshTokens, browserLogin, } from "@indigoai-us/hq-cloud";
|
|
15
|
+
export const DEFAULT_COGNITO = {
|
|
16
|
+
region: process.env.AWS_REGION ?? "us-east-1",
|
|
17
|
+
userPoolDomain: process.env.HQ_COGNITO_DOMAIN ?? "hq-vault-dev",
|
|
18
|
+
clientId: process.env.HQ_COGNITO_CLIENT_ID ?? "4mmujmjq3srakdueg656b9m0mp",
|
|
19
|
+
port: process.env.HQ_COGNITO_CALLBACK_PORT
|
|
20
|
+
? Number(process.env.HQ_COGNITO_CALLBACK_PORT)
|
|
21
|
+
: 8765,
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Return a non-expired Cognito access token, refreshing or browser-logging-in
|
|
25
|
+
* as needed. Cache lives at ~/.hq/cognito-tokens.json.
|
|
26
|
+
*
|
|
27
|
+
* Pass `interactive: false` from automated contexts where failing fast is
|
|
28
|
+
* better than opening a browser.
|
|
29
|
+
*/
|
|
30
|
+
export async function ensureCognitoToken(options = {}) {
|
|
31
|
+
const interactive = options.interactive ?? true;
|
|
32
|
+
const cached = loadCachedTokens();
|
|
33
|
+
if (cached && !isExpiring(cached, 120)) {
|
|
34
|
+
return cached.accessToken;
|
|
35
|
+
}
|
|
36
|
+
if (cached) {
|
|
37
|
+
try {
|
|
38
|
+
const refreshed = await refreshTokens(DEFAULT_COGNITO, cached.refreshToken);
|
|
39
|
+
return refreshed.accessToken;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// fall through to browser login
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (!interactive) {
|
|
46
|
+
throw new Error("No valid HQ session and interactive login is disabled. Run `hq login` first.");
|
|
47
|
+
}
|
|
48
|
+
const tokens = await browserLogin(DEFAULT_COGNITO);
|
|
49
|
+
return tokens.accessToken;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Refresh the cached Cognito session once and return the result. Used by
|
|
53
|
+
* `hq auth refresh` and the `hq-auth-refresh` bin. Never opens a browser —
|
|
54
|
+
* if no cached tokens exist or the refresh fails, throws.
|
|
55
|
+
*/
|
|
56
|
+
export async function refreshCachedSession() {
|
|
57
|
+
const cached = loadCachedTokens();
|
|
58
|
+
if (!cached) {
|
|
59
|
+
return { refreshed: false, reason: "no cached session" };
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
await refreshTokens(DEFAULT_COGNITO, cached.refreshToken);
|
|
63
|
+
return { refreshed: true };
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
return {
|
|
67
|
+
refreshed: false,
|
|
68
|
+
reason: err instanceof Error ? err.message : String(err),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=cognito-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cognito-session.js","sourceRoot":"","sources":["../../src/utils/cognito-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,YAAY,GAEb,MAAM,uBAAuB,CAAC;AAE/B,MAAM,CAAC,MAAM,eAAe,GAAsB;IAChD,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,WAAW;IAC7C,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,cAAc;IAC/D,QAAQ,EACN,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,4BAA4B;IAClE,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,wBAAwB;QACxC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;QAC9C,CAAC,CAAC,IAAI;CACT,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,UAErC,EAAE;IACJ,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC;IAChD,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAElC,IAAI,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;QACvC,OAAO,MAAM,CAAC,WAAW,CAAC;IAC5B,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,aAAa,CACnC,eAAe,EACf,MAAM,CAAC,YAAY,CACpB,CAAC;YACF,OAAO,SAAS,CAAC,WAAW,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,gCAAgC;QAClC,CAAC;IACH,CAAC;IAED,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,8EAA8E,CAC/E,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,eAAe,CAAC,CAAC;IACnD,OAAO,MAAM,CAAC,WAAW,CAAC;AAC5B,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IAIxC,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC3D,CAAC;IACD,IAAI,CAAC;QACH,MAAM,aAAa,CAAC,eAAe,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;QAC1D,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC7B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACzD,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/dist/utils/git.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
|
-
import
|
|
3
|
+
import simpleGit from 'simple-git';
|
|
4
4
|
export async function cloneRepo(repoUrl, targetDir, branch) {
|
|
5
5
|
const git = simpleGit();
|
|
6
6
|
const options = branch ? ['--branch', branch] : [];
|
package/dist/utils/git.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HQ root detection — walks up from cwd looking for HQ markers (US-004)
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Find the HQ root directory by walking up from cwd.
|
|
6
|
+
* Looks for CLAUDE.md or .claude/ directory as markers.
|
|
7
|
+
* Throws if not found.
|
|
8
|
+
*/
|
|
9
|
+
export declare function findHqRoot(): string;
|
|
10
|
+
//# sourceMappingURL=hq-root.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hq-root.d.ts","sourceRoot":"","sources":["../../src/utils/hq-root.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAcnC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HQ root detection — walks up from cwd looking for HQ markers (US-004)
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
/**
|
|
7
|
+
* Find the HQ root directory by walking up from cwd.
|
|
8
|
+
* Looks for CLAUDE.md or .claude/ directory as markers.
|
|
9
|
+
* Throws if not found.
|
|
10
|
+
*/
|
|
11
|
+
export function findHqRoot() {
|
|
12
|
+
let dir = process.cwd();
|
|
13
|
+
while (dir !== path.dirname(dir)) {
|
|
14
|
+
if (fs.existsSync(path.join(dir, 'CLAUDE.md')) ||
|
|
15
|
+
fs.existsSync(path.join(dir, '.claude'))) {
|
|
16
|
+
return dir;
|
|
17
|
+
}
|
|
18
|
+
dir = path.dirname(dir);
|
|
19
|
+
}
|
|
20
|
+
throw new Error('Could not find HQ root. Run this command from within your HQ directory.');
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=hq-root.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hq-root.js","sourceRoot":"","sources":["../../src/utils/hq-root.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;;GAIG;AACH,MAAM,UAAU,UAAU;IACxB,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACxB,OAAO,GAAG,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,IACE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;YAC1C,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,EACxC,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;QACD,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IACD,MAAM,IAAI,KAAK,CACb,yEAAyE,CAC1E,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integrity verification — SHA256 hash and RSA signature checks (US-005)
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Verify a file's SHA256 hash matches the expected value.
|
|
6
|
+
*/
|
|
7
|
+
export declare function verifySha256(filePath: string, expectedHash: string): Promise<boolean>;
|
|
8
|
+
/**
|
|
9
|
+
* Verify an RSA signature of a SHA256 hash using the registry public key.
|
|
10
|
+
* The public key is expected at packages/.keys/registry-public.pem.
|
|
11
|
+
* Returns false (does not throw) if the key file is missing.
|
|
12
|
+
*/
|
|
13
|
+
export declare function verifyRsaSignature(sha256Hash: string, signature: string, publicKeyPath?: string): boolean;
|
|
14
|
+
//# sourceMappingURL=integrity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrity.d.ts","sourceRoot":"","sources":["../../src/utils/integrity.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH;;GAEG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,OAAO,CAAC,CAYlB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAeT"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integrity verification — SHA256 hash and RSA signature checks (US-005)
|
|
3
|
+
*/
|
|
4
|
+
import * as crypto from 'crypto';
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import { findHqRoot } from './hq-root.js';
|
|
8
|
+
/**
|
|
9
|
+
* Verify a file's SHA256 hash matches the expected value.
|
|
10
|
+
*/
|
|
11
|
+
export async function verifySha256(filePath, expectedHash) {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const hash = crypto.createHash('sha256');
|
|
14
|
+
const stream = fs.createReadStream(filePath);
|
|
15
|
+
stream.on('data', (chunk) => hash.update(chunk));
|
|
16
|
+
stream.on('end', () => {
|
|
17
|
+
const computed = hash.digest('hex');
|
|
18
|
+
resolve(computed === expectedHash.toLowerCase());
|
|
19
|
+
});
|
|
20
|
+
stream.on('error', reject);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Verify an RSA signature of a SHA256 hash using the registry public key.
|
|
25
|
+
* The public key is expected at packages/.keys/registry-public.pem.
|
|
26
|
+
* Returns false (does not throw) if the key file is missing.
|
|
27
|
+
*/
|
|
28
|
+
export function verifyRsaSignature(sha256Hash, signature, publicKeyPath) {
|
|
29
|
+
const keyPath = publicKeyPath ??
|
|
30
|
+
path.resolve(findHqRoot(), 'packages', '.keys', 'registry-public.pem');
|
|
31
|
+
if (!fs.existsSync(keyPath)) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
const publicKey = fs.readFileSync(keyPath, 'utf-8');
|
|
35
|
+
const verifier = crypto.createVerify('SHA256');
|
|
36
|
+
verifier.update(sha256Hash);
|
|
37
|
+
verifier.end();
|
|
38
|
+
return verifier.verify(publicKey, Buffer.from(signature, 'base64'));
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=integrity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrity.js","sourceRoot":"","sources":["../../src/utils/integrity.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAgB,EAChB,YAAoB;IAEpB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAE7C,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACjD,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACpC,OAAO,CAAC,QAAQ,KAAK,YAAY,CAAC,WAAW,EAAE,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,UAAkB,EAClB,SAAiB,EACjB,aAAsB;IAEtB,MAAM,OAAO,GACX,aAAa;QACb,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,qBAAqB,CAAC,CAAC;IAEzE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC/C,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,CAAC;IAEf,OAAO,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;AACtE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/utils/manifest.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAM5F,wBAAgB,UAAU,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/utils/manifest.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAM5F,wBAAgB,UAAU,IAAI,MAAM,CASnC;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAOnE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI,CAI7E;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAO1D;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAIhE;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAO1D;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAGjE;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAaxE;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CASrD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD"}
|
package/dist/utils/manifest.js
CHANGED
|
@@ -6,14 +6,11 @@ const LOCK_FILE = 'modules.lock';
|
|
|
6
6
|
const STATE_FILE = '.hq-sync-state.json';
|
|
7
7
|
export function findHqRoot() {
|
|
8
8
|
let dir = process.cwd();
|
|
9
|
-
while (
|
|
9
|
+
while (dir !== '/') {
|
|
10
10
|
if (fs.existsSync(path.join(dir, '.claude')) || fs.existsSync(path.join(dir, 'workers'))) {
|
|
11
11
|
return dir;
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
if (parent === dir)
|
|
15
|
-
break; // Reached filesystem root (works on Windows and Unix)
|
|
16
|
-
dir = parent;
|
|
13
|
+
dir = path.dirname(dir);
|
|
17
14
|
}
|
|
18
15
|
return process.cwd();
|
|
19
16
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/utils/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAGhC,MAAM,aAAa,GAAG,cAAc,CAAC;AACrC,MAAM,SAAS,GAAG,cAAc,CAAC;AACjC,MAAM,UAAU,GAAG,qBAAqB,CAAC;AAEzC,MAAM,UAAU,UAAU;IACxB,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACxB,OAAO,
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/utils/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry client — reads registry URL from packages/sources.yaml and provides
|
|
3
|
+
* API methods for the HQ package registry (US-004 base, US-005 full client).
|
|
4
|
+
*
|
|
5
|
+
* Auth tokens are NEVER written to stdout or logs.
|
|
6
|
+
*/
|
|
7
|
+
export interface PackageMeta {
|
|
8
|
+
slug: string;
|
|
9
|
+
name: string;
|
|
10
|
+
description: string;
|
|
11
|
+
tier: string;
|
|
12
|
+
latest_version: string;
|
|
13
|
+
author?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface PackageListResponse {
|
|
16
|
+
packages: PackageMeta[];
|
|
17
|
+
}
|
|
18
|
+
export interface PackageResponse {
|
|
19
|
+
package: PackageMeta;
|
|
20
|
+
versions: {
|
|
21
|
+
version: string;
|
|
22
|
+
published_at: string;
|
|
23
|
+
}[];
|
|
24
|
+
}
|
|
25
|
+
export interface EntitlementEntry {
|
|
26
|
+
slug: string;
|
|
27
|
+
tier: string;
|
|
28
|
+
granted_at: string;
|
|
29
|
+
expires_at?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface EntitlementListResponse {
|
|
32
|
+
entitlements: EntitlementEntry[];
|
|
33
|
+
}
|
|
34
|
+
export interface EntitlementCheckResponse {
|
|
35
|
+
entitled: boolean;
|
|
36
|
+
tier?: string;
|
|
37
|
+
expires_at?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface DownloadResponse {
|
|
40
|
+
url: string;
|
|
41
|
+
sha256: string;
|
|
42
|
+
signature?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Read the registry URL from packages/sources.yaml in the user's HQ root.
|
|
46
|
+
* Returns the URL of the first source entry.
|
|
47
|
+
* Throws if sources.yaml is missing or has no sources.
|
|
48
|
+
*/
|
|
49
|
+
export declare function getRegistryUrl(): string;
|
|
50
|
+
export declare class RegistryClient {
|
|
51
|
+
private baseUrl;
|
|
52
|
+
private authToken?;
|
|
53
|
+
constructor(baseUrl: string, authToken?: string);
|
|
54
|
+
private headers;
|
|
55
|
+
private request;
|
|
56
|
+
listPackages(opts?: {
|
|
57
|
+
tier?: string;
|
|
58
|
+
q?: string;
|
|
59
|
+
}): Promise<PackageListResponse>;
|
|
60
|
+
getPackage(slug: string): Promise<PackageResponse>;
|
|
61
|
+
getMyEntitlements(): Promise<EntitlementListResponse>;
|
|
62
|
+
checkEntitlement(slug: string): Promise<EntitlementCheckResponse>;
|
|
63
|
+
getDownloadUrl(slug: string, version?: string): Promise<DownloadResponse>;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=registry-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-client.d.ts","sourceRoot":"","sources":["../../src/utils/registry-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAsBH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACvD;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,gBAAgB,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAkBvC;AAMD,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAC,CAAS;gBAEf,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;IAO/C,OAAO,CAAC,OAAO;YAUD,OAAO;IAkCf,YAAY,CAAC,IAAI,CAAC,EAAE;QACxB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,CAAC,CAAC,EAAE,MAAM,CAAC;KACZ,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAW1B,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAMlD,iBAAiB,IAAI,OAAO,CAAC,uBAAuB,CAAC;IAMrD,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAQjE,cAAc,CAClB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,gBAAgB,CAAC;CAU7B"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry client — reads registry URL from packages/sources.yaml and provides
|
|
3
|
+
* API methods for the HQ package registry (US-004 base, US-005 full client).
|
|
4
|
+
*
|
|
5
|
+
* Auth tokens are NEVER written to stdout or logs.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import * as yaml from 'js-yaml';
|
|
10
|
+
import { findHqRoot } from './hq-root.js';
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// URL helper (unchanged from US-004)
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
/**
|
|
15
|
+
* Read the registry URL from packages/sources.yaml in the user's HQ root.
|
|
16
|
+
* Returns the URL of the first source entry.
|
|
17
|
+
* Throws if sources.yaml is missing or has no sources.
|
|
18
|
+
*/
|
|
19
|
+
export function getRegistryUrl() {
|
|
20
|
+
const hqRoot = findHqRoot();
|
|
21
|
+
const sourcesPath = path.join(hqRoot, 'packages', 'sources.yaml');
|
|
22
|
+
if (!fs.existsSync(sourcesPath)) {
|
|
23
|
+
throw new Error(`No packages/sources.yaml found at ${sourcesPath}. Is your HQ packages directory set up?`);
|
|
24
|
+
}
|
|
25
|
+
const content = fs.readFileSync(sourcesPath, 'utf-8');
|
|
26
|
+
const parsed = yaml.load(content);
|
|
27
|
+
if (!parsed?.sources?.length) {
|
|
28
|
+
throw new Error('No sources defined in packages/sources.yaml');
|
|
29
|
+
}
|
|
30
|
+
return parsed.sources[0].url;
|
|
31
|
+
}
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// RegistryClient
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
export class RegistryClient {
|
|
36
|
+
baseUrl;
|
|
37
|
+
authToken;
|
|
38
|
+
constructor(baseUrl, authToken) {
|
|
39
|
+
this.baseUrl = baseUrl.replace(/\/+$/, '');
|
|
40
|
+
this.authToken = authToken;
|
|
41
|
+
}
|
|
42
|
+
// ---- helpers ----
|
|
43
|
+
headers(auth) {
|
|
44
|
+
const h = {
|
|
45
|
+
Accept: 'application/json',
|
|
46
|
+
};
|
|
47
|
+
if (auth && this.authToken) {
|
|
48
|
+
h['Authorization'] = `Bearer ${this.authToken}`;
|
|
49
|
+
}
|
|
50
|
+
return h;
|
|
51
|
+
}
|
|
52
|
+
async request(method, urlPath, opts = {}) {
|
|
53
|
+
const auth = opts.auth ?? false;
|
|
54
|
+
const url = `${this.baseUrl}${urlPath}`;
|
|
55
|
+
const init = {
|
|
56
|
+
method,
|
|
57
|
+
headers: this.headers(auth),
|
|
58
|
+
signal: AbortSignal.timeout(opts.timeout ?? 30_000),
|
|
59
|
+
};
|
|
60
|
+
if (opts.body) {
|
|
61
|
+
init.headers['Content-Type'] =
|
|
62
|
+
'application/json';
|
|
63
|
+
init.body = JSON.stringify(opts.body);
|
|
64
|
+
}
|
|
65
|
+
const res = await fetch(url, init);
|
|
66
|
+
if (!res.ok) {
|
|
67
|
+
const text = await res.text().catch(() => '');
|
|
68
|
+
throw new Error(`Registry API ${method} ${urlPath} failed (${res.status}): ${text}`);
|
|
69
|
+
}
|
|
70
|
+
return (await res.json());
|
|
71
|
+
}
|
|
72
|
+
// ---- public (no auth) ----
|
|
73
|
+
async listPackages(opts) {
|
|
74
|
+
const params = new URLSearchParams();
|
|
75
|
+
if (opts?.tier)
|
|
76
|
+
params.set('tier', opts.tier);
|
|
77
|
+
if (opts?.q)
|
|
78
|
+
params.set('q', opts.q);
|
|
79
|
+
const qs = params.toString();
|
|
80
|
+
return this.request('GET', `/packages${qs ? `?${qs}` : ''}`);
|
|
81
|
+
}
|
|
82
|
+
async getPackage(slug) {
|
|
83
|
+
return this.request('GET', `/packages/${encodeURIComponent(slug)}`);
|
|
84
|
+
}
|
|
85
|
+
// ---- auth required ----
|
|
86
|
+
async getMyEntitlements() {
|
|
87
|
+
return this.request('GET', '/entitlements', {
|
|
88
|
+
auth: true,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
async checkEntitlement(slug) {
|
|
92
|
+
return this.request('GET', `/entitlements/${encodeURIComponent(slug)}`, { auth: true });
|
|
93
|
+
}
|
|
94
|
+
async getDownloadUrl(slug, version) {
|
|
95
|
+
const params = new URLSearchParams();
|
|
96
|
+
if (version)
|
|
97
|
+
params.set('version', version);
|
|
98
|
+
const qs = params.toString();
|
|
99
|
+
return this.request('GET', `/packages/${encodeURIComponent(slug)}/download${qs ? `?${qs}` : ''}`, { auth: true });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=registry-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-client.js","sourceRoot":"","sources":["../../src/utils/registry-client.ts"],"names":[],"mappings":"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"}
|