chief-helm 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +220 -0
- package/dist/commands/config.d.ts +26 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +111 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/inputs.d.ts +21 -0
- package/dist/commands/inputs.d.ts.map +1 -0
- package/dist/commands/inputs.js +158 -0
- package/dist/commands/inputs.js.map +1 -0
- package/dist/commands/push.d.ts +21 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/push.js +51 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/secrets.d.ts +21 -0
- package/dist/commands/secrets.d.ts.map +1 -0
- package/dist/commands/secrets.js +110 -0
- package/dist/commands/secrets.js.map +1 -0
- package/dist/commands/setup.d.ts +24 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +421 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/status.d.ts +20 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +184 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/sync.d.ts +19 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +47 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/core/config.d.ts +74 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +182 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/git.d.ts +73 -0
- package/dist/core/git.d.ts.map +1 -0
- package/dist/core/git.js +188 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/inputs.d.ts +40 -0
- package/dist/core/inputs.d.ts.map +1 -0
- package/dist/core/inputs.js +360 -0
- package/dist/core/inputs.js.map +1 -0
- package/dist/core/repo.d.ts +71 -0
- package/dist/core/repo.d.ts.map +1 -0
- package/dist/core/repo.js +152 -0
- package/dist/core/repo.js.map +1 -0
- package/dist/core/secrets.d.ts +79 -0
- package/dist/core/secrets.d.ts.map +1 -0
- package/dist/core/secrets.js +168 -0
- package/dist/core/secrets.js.map +1 -0
- package/dist/core/state.d.ts +46 -0
- package/dist/core/state.d.ts.map +1 -0
- package/dist/core/state.js +119 -0
- package/dist/core/state.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +163 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +210 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/ui/components/Header.d.ts +32 -0
- package/dist/ui/components/Header.d.ts.map +1 -0
- package/dist/ui/components/Header.js +15 -0
- package/dist/ui/components/Header.js.map +1 -0
- package/dist/ui/components/Panel.d.ts +30 -0
- package/dist/ui/components/Panel.d.ts.map +1 -0
- package/dist/ui/components/Panel.js +15 -0
- package/dist/ui/components/Panel.js.map +1 -0
- package/dist/ui/components/StatusRow.d.ts +39 -0
- package/dist/ui/components/StatusRow.d.ts.map +1 -0
- package/dist/ui/components/StatusRow.js +27 -0
- package/dist/ui/components/StatusRow.js.map +1 -0
- package/dist/ui/theme.d.ts +60 -0
- package/dist/ui/theme.d.ts.map +1 -0
- package/dist/ui/theme.js +60 -0
- package/dist/ui/theme.js.map +1 -0
- package/dist/utils/errors.d.ts +50 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +63 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/format.d.ts +66 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +107 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/logger.d.ts +35 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +71 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +53 -0
package/dist/core/git.js
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Git operations for HELM.
|
|
3
|
+
*
|
|
4
|
+
* All git interactions are routed through this module. Every function
|
|
5
|
+
* operates on the personal instance repo at the path provided by the
|
|
6
|
+
* caller (obtained from repoPath() in core/repo.ts).
|
|
7
|
+
*
|
|
8
|
+
* Git discipline enforced by this module:
|
|
9
|
+
* - pullLatest() must be called before any flow run.
|
|
10
|
+
* - commitAndPush() must be called after any successful flow run.
|
|
11
|
+
* - Merge conflicts abort all operations with explicit manual steps.
|
|
12
|
+
* - git add is always called with an explicit file list — never -A.
|
|
13
|
+
*
|
|
14
|
+
* Push failures after a completed run are non-fatal: they surface as a
|
|
15
|
+
* warning with the manual push command so the user can recover without
|
|
16
|
+
* re-running the flow.
|
|
17
|
+
*/
|
|
18
|
+
import { simpleGit } from "simple-git";
|
|
19
|
+
import chalk from "chalk";
|
|
20
|
+
import { HelmError } from "../utils/errors.js";
|
|
21
|
+
// ─── Internal Helpers ─────────────────────────────────────────────────────────
|
|
22
|
+
/**
|
|
23
|
+
* Returns a configured SimpleGit instance scoped to the given repo root.
|
|
24
|
+
* Throws HelmError if the directory does not exist or is not a git repo.
|
|
25
|
+
*
|
|
26
|
+
* @param repoRoot - Absolute path to the git repository root.
|
|
27
|
+
*/
|
|
28
|
+
function getGit(repoRoot) {
|
|
29
|
+
return simpleGit(repoRoot);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Returns true if the status result indicates a merge conflict is in
|
|
33
|
+
* progress (files in BOTH_MODIFIED, BOTH_ADDED, etc. states).
|
|
34
|
+
*/
|
|
35
|
+
function hasConflicts(status) {
|
|
36
|
+
return status.conflicted.length > 0;
|
|
37
|
+
}
|
|
38
|
+
// ─── Public API ───────────────────────────────────────────────────────────────
|
|
39
|
+
/**
|
|
40
|
+
* Pulls the latest changes from the remote origin for the current branch.
|
|
41
|
+
*
|
|
42
|
+
* Fails fast if:
|
|
43
|
+
* - The pull results in a merge conflict.
|
|
44
|
+
* - The git command itself fails (no remote, auth error, etc.).
|
|
45
|
+
*
|
|
46
|
+
* This must be called before any flow run begins to ensure the agent
|
|
47
|
+
* instructions and config are up to date.
|
|
48
|
+
*
|
|
49
|
+
* @param repoRoot - Absolute path to the instance repo.
|
|
50
|
+
* @throws {HelmError} On merge conflict or pull failure.
|
|
51
|
+
*/
|
|
52
|
+
export async function pullLatest(repoRoot) {
|
|
53
|
+
const git = getGit(repoRoot);
|
|
54
|
+
try {
|
|
55
|
+
await git.pull();
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
59
|
+
throw new HelmError(`git pull failed: ${detail}`, [
|
|
60
|
+
"Resolve manually:",
|
|
61
|
+
" 1. cd " + repoRoot,
|
|
62
|
+
" 2. git status",
|
|
63
|
+
" 3. Resolve any conflicts, then: git add . && git commit",
|
|
64
|
+
" 4. Re-run your helm command.",
|
|
65
|
+
].join("\n "));
|
|
66
|
+
}
|
|
67
|
+
const status = await getGit(repoRoot).status();
|
|
68
|
+
if (hasConflicts(status)) {
|
|
69
|
+
throw new HelmError("git pull introduced merge conflicts — cannot continue.", [
|
|
70
|
+
"Resolve manually:",
|
|
71
|
+
" 1. cd " + repoRoot,
|
|
72
|
+
" 2. git status (lists conflicted files)",
|
|
73
|
+
" 3. Edit each conflicted file, then: git add <file>",
|
|
74
|
+
" 4. git commit",
|
|
75
|
+
" 5. Re-run your helm command.",
|
|
76
|
+
].join("\n "));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Returns the current working tree status of the repo.
|
|
81
|
+
*
|
|
82
|
+
* @param repoRoot - Absolute path to the instance repo.
|
|
83
|
+
* @throws {HelmError} If git status cannot be read.
|
|
84
|
+
*/
|
|
85
|
+
export async function getRepoStatus(repoRoot) {
|
|
86
|
+
const git = getGit(repoRoot);
|
|
87
|
+
try {
|
|
88
|
+
const status = await git.status();
|
|
89
|
+
const fileCount = status.modified.length +
|
|
90
|
+
status.not_added.length +
|
|
91
|
+
status.created.length +
|
|
92
|
+
status.deleted.length +
|
|
93
|
+
status.renamed.length;
|
|
94
|
+
return { clean: status.isClean(), fileCount };
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
98
|
+
throw new HelmError(`Could not read git status: ${detail}`, `Ensure ${repoRoot} is a valid git repository.`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Stages an explicit list of files, commits with the given message,
|
|
103
|
+
* and pushes to origin.
|
|
104
|
+
*
|
|
105
|
+
* If the push fails the commit is preserved locally and the function
|
|
106
|
+
* prints a recoverable warning rather than throwing. This matches the
|
|
107
|
+
* PRD behaviour: a completed run's outputs are never discarded due to
|
|
108
|
+
* a push failure.
|
|
109
|
+
*
|
|
110
|
+
* @param repoRoot - Absolute path to the instance repo.
|
|
111
|
+
* @param files - Explicit list of repo-relative paths to stage.
|
|
112
|
+
* @param message - Commit message (caller applies [tag] prefix convention).
|
|
113
|
+
* @returns True if the push succeeded; false if it failed (warning printed).
|
|
114
|
+
* @throws {HelmError} If the commit itself fails.
|
|
115
|
+
*/
|
|
116
|
+
export async function commitAndPush(repoRoot, files, message) {
|
|
117
|
+
const git = getGit(repoRoot);
|
|
118
|
+
try {
|
|
119
|
+
await git.add(files);
|
|
120
|
+
await git.commit(message);
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
124
|
+
throw new HelmError(`git commit failed: ${detail}`, `Check git status in ${repoRoot} and resolve any issues, then push manually.`);
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
await git.push();
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
132
|
+
console.warn(chalk.yellow(`\n ⚠ git push failed: ${detail}\n → Push manually: cd ${repoRoot} && git push`));
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Stages all tracked modified files and pushes with a given commit message.
|
|
138
|
+
* Unlike commitAndPush(), this uses `git add -u` (tracked files only) rather
|
|
139
|
+
* than an explicit file list. Intended for helm push where the user is
|
|
140
|
+
* explicitly choosing to push whatever is dirty.
|
|
141
|
+
*
|
|
142
|
+
* @param repoRoot - Absolute path to the instance repo.
|
|
143
|
+
* @param message - Commit message.
|
|
144
|
+
* @returns True if push succeeded.
|
|
145
|
+
* @throws {HelmError} If there is nothing to commit or commit fails.
|
|
146
|
+
*/
|
|
147
|
+
export async function addAllAndPush(repoRoot, message) {
|
|
148
|
+
const git = getGit(repoRoot);
|
|
149
|
+
const status = await git.status();
|
|
150
|
+
const isDirty = status.modified.length > 0 ||
|
|
151
|
+
status.not_added.length > 0 ||
|
|
152
|
+
status.created.length > 0 ||
|
|
153
|
+
status.deleted.length > 0;
|
|
154
|
+
if (!isDirty) {
|
|
155
|
+
throw new HelmError("Nothing to commit — the repo is already clean.", "Make changes first, or run: helm sync to pull the latest.");
|
|
156
|
+
}
|
|
157
|
+
try {
|
|
158
|
+
await git.add("-A");
|
|
159
|
+
await git.commit(message);
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
163
|
+
throw new HelmError(`git commit failed: ${detail}`, `Check git status in ${repoRoot} and resolve any issues.`);
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
await git.push();
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
171
|
+
console.warn(chalk.yellow(`\n ⚠ git push failed: ${detail}\n → Push manually: cd ${repoRoot} && git push`));
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Returns true if the `git` executable is available in PATH.
|
|
177
|
+
* Used by the startup check in index.ts.
|
|
178
|
+
*/
|
|
179
|
+
export async function isGitAvailable() {
|
|
180
|
+
try {
|
|
181
|
+
await simpleGit().raw(["--version"]);
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/core/git.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Input credential definitions and connectivity tests.
|
|
3
|
+
*
|
|
4
|
+
* Defines which secret keys each input requires and provides the test
|
|
5
|
+
* function that verifies a live connection using those credentials.
|
|
6
|
+
*
|
|
7
|
+
* Test calls make real HTTP requests using the Node 20 built-in fetch.
|
|
8
|
+
* On success, each test returns a human-readable detail string (email
|
|
9
|
+
* address, calendar count, etc.) confirming the credential works.
|
|
10
|
+
*
|
|
11
|
+
* On failure with HTTP 401, the test reports the credential as invalid
|
|
12
|
+
* and instructs the user to refresh it via helm secrets set. No silent
|
|
13
|
+
* token refresh is attempted in Phase 1 — that is Phase 2 scope.
|
|
14
|
+
*
|
|
15
|
+
* Secret values retrieved from the keychain are used directly in HTTP
|
|
16
|
+
* Authorization headers and are never included in any log output or
|
|
17
|
+
* error message.
|
|
18
|
+
*/
|
|
19
|
+
import type { InputTestResult } from "../types/index.js";
|
|
20
|
+
/**
|
|
21
|
+
* Ordered list of OS keychain key names required by each input.
|
|
22
|
+
* Used during helm setup to prompt for each credential and during
|
|
23
|
+
* helm inputs test to retrieve them for connectivity checks.
|
|
24
|
+
*
|
|
25
|
+
* Keys must match the names used in helm secrets set commands documented
|
|
26
|
+
* in SETUP.md.
|
|
27
|
+
*/
|
|
28
|
+
export declare const INPUT_CREDENTIAL_KEYS: Record<string, string[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Runs the connectivity test for the given input ID.
|
|
31
|
+
*
|
|
32
|
+
* Returns an InputTestResult regardless of outcome — errors are
|
|
33
|
+
* represented in the result rather than thrown, so callers can
|
|
34
|
+
* display results for multiple inputs without short-circuiting.
|
|
35
|
+
*
|
|
36
|
+
* @param inputId - The input identifier to test (e.g. "gmail").
|
|
37
|
+
* @param username - Active username whose credentials to use.
|
|
38
|
+
*/
|
|
39
|
+
export declare function testInput(inputId: string, username: string): Promise<InputTestResult>;
|
|
40
|
+
//# sourceMappingURL=inputs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inputs.d.ts","sourceRoot":"","sources":["../../src/core/inputs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAKzD;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAc1D,CAAC;AA4VF;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,eAAe,CAAC,CAoB1B"}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Input credential definitions and connectivity tests.
|
|
3
|
+
*
|
|
4
|
+
* Defines which secret keys each input requires and provides the test
|
|
5
|
+
* function that verifies a live connection using those credentials.
|
|
6
|
+
*
|
|
7
|
+
* Test calls make real HTTP requests using the Node 20 built-in fetch.
|
|
8
|
+
* On success, each test returns a human-readable detail string (email
|
|
9
|
+
* address, calendar count, etc.) confirming the credential works.
|
|
10
|
+
*
|
|
11
|
+
* On failure with HTTP 401, the test reports the credential as invalid
|
|
12
|
+
* and instructs the user to refresh it via helm secrets set. No silent
|
|
13
|
+
* token refresh is attempted in Phase 1 — that is Phase 2 scope.
|
|
14
|
+
*
|
|
15
|
+
* Secret values retrieved from the keychain are used directly in HTTP
|
|
16
|
+
* Authorization headers and are never included in any log output or
|
|
17
|
+
* error message.
|
|
18
|
+
*/
|
|
19
|
+
import { getSecret } from "./secrets.js";
|
|
20
|
+
// ─── Credential Key Definitions ───────────────────────────────────────────────
|
|
21
|
+
/**
|
|
22
|
+
* Ordered list of OS keychain key names required by each input.
|
|
23
|
+
* Used during helm setup to prompt for each credential and during
|
|
24
|
+
* helm inputs test to retrieve them for connectivity checks.
|
|
25
|
+
*
|
|
26
|
+
* Keys must match the names used in helm secrets set commands documented
|
|
27
|
+
* in SETUP.md.
|
|
28
|
+
*/
|
|
29
|
+
export const INPUT_CREDENTIAL_KEYS = {
|
|
30
|
+
gmail: [
|
|
31
|
+
"GMAIL_CLIENT_ID",
|
|
32
|
+
"GMAIL_CLIENT_SECRET",
|
|
33
|
+
"GMAIL_OAUTH_REFRESH_TOKEN",
|
|
34
|
+
],
|
|
35
|
+
google_calendar: [
|
|
36
|
+
"GCAL_CLIENT_ID",
|
|
37
|
+
"GCAL_CLIENT_SECRET",
|
|
38
|
+
"GCAL_OAUTH_REFRESH_TOKEN",
|
|
39
|
+
],
|
|
40
|
+
google_maps: ["GOOGLE_MAPS_API_KEY"],
|
|
41
|
+
todoist: ["TODOIST_API_TOKEN"],
|
|
42
|
+
zoom: ["ZOOM_ACCOUNT_ID", "ZOOM_CLIENT_ID", "ZOOM_CLIENT_SECRET"],
|
|
43
|
+
};
|
|
44
|
+
// ─── Internal HTTP Helpers ────────────────────────────────────────────────────
|
|
45
|
+
/**
|
|
46
|
+
* Exchanges a Google OAuth refresh token for a short-lived access token
|
|
47
|
+
* using the Google token endpoint. Returns the access token string.
|
|
48
|
+
*
|
|
49
|
+
* The refresh token and client credentials are never included in logs or
|
|
50
|
+
* error output.
|
|
51
|
+
*
|
|
52
|
+
* @throws When the token endpoint returns a non-200 status.
|
|
53
|
+
*/
|
|
54
|
+
async function googleRefreshToAccessToken(clientId, clientSecret, refreshToken) {
|
|
55
|
+
const body = new URLSearchParams({
|
|
56
|
+
client_id: clientId,
|
|
57
|
+
client_secret: clientSecret,
|
|
58
|
+
refresh_token: refreshToken,
|
|
59
|
+
grant_type: "refresh_token",
|
|
60
|
+
});
|
|
61
|
+
const res = await fetch("https://oauth2.googleapis.com/token", {
|
|
62
|
+
method: "POST",
|
|
63
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
64
|
+
body: body.toString(),
|
|
65
|
+
});
|
|
66
|
+
if (!res.ok) {
|
|
67
|
+
const status = res.status;
|
|
68
|
+
const reason = status === 401 || status === 400
|
|
69
|
+
? "credential rejected"
|
|
70
|
+
: `HTTP ${status}`;
|
|
71
|
+
throw new Error(reason);
|
|
72
|
+
}
|
|
73
|
+
const data = (await res.json());
|
|
74
|
+
return data.access_token;
|
|
75
|
+
}
|
|
76
|
+
// ─── Per-Input Test Functions ────────────────────────────────────────────────
|
|
77
|
+
/**
|
|
78
|
+
* Tests the Gmail connection by exchanging the stored refresh token for
|
|
79
|
+
* an access token and fetching the user's Gmail profile.
|
|
80
|
+
* Returns the verified email address on success.
|
|
81
|
+
*/
|
|
82
|
+
async function testGmail(username) {
|
|
83
|
+
const clientId = await getSecret(username, "GMAIL_CLIENT_ID");
|
|
84
|
+
const clientSecret = await getSecret(username, "GMAIL_CLIENT_SECRET");
|
|
85
|
+
const refreshToken = await getSecret(username, "GMAIL_OAUTH_REFRESH_TOKEN");
|
|
86
|
+
if (!clientId || !clientSecret || !refreshToken) {
|
|
87
|
+
return {
|
|
88
|
+
inputId: "gmail",
|
|
89
|
+
ok: false,
|
|
90
|
+
error: "One or more Gmail credentials are missing.",
|
|
91
|
+
fix: "Run: helm secrets set GMAIL_CLIENT_ID && helm secrets set GMAIL_CLIENT_SECRET && helm secrets set GMAIL_OAUTH_REFRESH_TOKEN",
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
const accessToken = await googleRefreshToAccessToken(clientId, clientSecret, refreshToken);
|
|
96
|
+
const res = await fetch("https://gmail.googleapis.com/gmail/v1/users/me/profile", { headers: { Authorization: `Bearer ${accessToken}` } });
|
|
97
|
+
if (res.status === 401) {
|
|
98
|
+
return {
|
|
99
|
+
inputId: "gmail",
|
|
100
|
+
ok: false,
|
|
101
|
+
error: "Gmail access token was rejected (401).",
|
|
102
|
+
fix: "Your refresh token may have expired. Run: helm secrets set GMAIL_OAUTH_REFRESH_TOKEN with a fresh token.",
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
if (!res.ok) {
|
|
106
|
+
return {
|
|
107
|
+
inputId: "gmail",
|
|
108
|
+
ok: false,
|
|
109
|
+
error: `Gmail API returned HTTP ${res.status}.`,
|
|
110
|
+
fix: "Check your Google Cloud project quota and API enablement, then retry.",
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const data = (await res.json());
|
|
114
|
+
return { inputId: "gmail", ok: true, detail: data.emailAddress };
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
118
|
+
return {
|
|
119
|
+
inputId: "gmail",
|
|
120
|
+
ok: false,
|
|
121
|
+
error: `Gmail test failed: ${msg}`,
|
|
122
|
+
fix: "Check your Gmail credentials and internet connection, then retry.",
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Tests the Google Calendar connection by listing the user's calendars.
|
|
128
|
+
* Returns the calendar count on success.
|
|
129
|
+
*/
|
|
130
|
+
async function testGoogleCalendar(username) {
|
|
131
|
+
const clientId = await getSecret(username, "GCAL_CLIENT_ID");
|
|
132
|
+
const clientSecret = await getSecret(username, "GCAL_CLIENT_SECRET");
|
|
133
|
+
const refreshToken = await getSecret(username, "GCAL_OAUTH_REFRESH_TOKEN");
|
|
134
|
+
if (!clientId || !clientSecret || !refreshToken) {
|
|
135
|
+
return {
|
|
136
|
+
inputId: "google_calendar",
|
|
137
|
+
ok: false,
|
|
138
|
+
error: "One or more Google Calendar credentials are missing.",
|
|
139
|
+
fix: "Run: helm secrets set GCAL_CLIENT_ID && helm secrets set GCAL_CLIENT_SECRET && helm secrets set GCAL_OAUTH_REFRESH_TOKEN",
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
const accessToken = await googleRefreshToAccessToken(clientId, clientSecret, refreshToken);
|
|
144
|
+
const res = await fetch("https://www.googleapis.com/calendar/v3/users/me/calendarList", { headers: { Authorization: `Bearer ${accessToken}` } });
|
|
145
|
+
if (res.status === 401) {
|
|
146
|
+
return {
|
|
147
|
+
inputId: "google_calendar",
|
|
148
|
+
ok: false,
|
|
149
|
+
error: "Google Calendar access token was rejected (401).",
|
|
150
|
+
fix: "Your refresh token may have expired. Run: helm secrets set GCAL_OAUTH_REFRESH_TOKEN with a fresh token.",
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
if (!res.ok) {
|
|
154
|
+
return {
|
|
155
|
+
inputId: "google_calendar",
|
|
156
|
+
ok: false,
|
|
157
|
+
error: `Google Calendar API returned HTTP ${res.status}.`,
|
|
158
|
+
fix: "Check your Google Cloud project quota and Calendar API enablement, then retry.",
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
const data = (await res.json());
|
|
162
|
+
const count = data.items?.length ?? 0;
|
|
163
|
+
return {
|
|
164
|
+
inputId: "google_calendar",
|
|
165
|
+
ok: true,
|
|
166
|
+
detail: `${count} calendar${count !== 1 ? "s" : ""} found`,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
171
|
+
return {
|
|
172
|
+
inputId: "google_calendar",
|
|
173
|
+
ok: false,
|
|
174
|
+
error: `Google Calendar test failed: ${msg}`,
|
|
175
|
+
fix: "Check your Calendar credentials and internet connection, then retry.",
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Tests the Google Maps connection by geocoding a known address.
|
|
181
|
+
* Returns "geocoding OK" on success.
|
|
182
|
+
*/
|
|
183
|
+
async function testGoogleMaps(username) {
|
|
184
|
+
const apiKey = await getSecret(username, "GOOGLE_MAPS_API_KEY");
|
|
185
|
+
if (!apiKey) {
|
|
186
|
+
return {
|
|
187
|
+
inputId: "google_maps",
|
|
188
|
+
ok: false,
|
|
189
|
+
error: "Google Maps API key is missing.",
|
|
190
|
+
fix: "Run: helm secrets set GOOGLE_MAPS_API_KEY",
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
try {
|
|
194
|
+
const url = new URL("https://maps.googleapis.com/maps/api/geocode/json");
|
|
195
|
+
url.searchParams.set("address", "1600 Amphitheatre Pkwy, Mountain View, CA");
|
|
196
|
+
url.searchParams.set("key", apiKey);
|
|
197
|
+
const res = await fetch(url.toString());
|
|
198
|
+
if (!res.ok) {
|
|
199
|
+
return {
|
|
200
|
+
inputId: "google_maps",
|
|
201
|
+
ok: false,
|
|
202
|
+
error: `Google Maps API returned HTTP ${res.status}.`,
|
|
203
|
+
fix: "Check your API key and Maps API enablement in Google Cloud Console.",
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
const data = (await res.json());
|
|
207
|
+
if (data.status === "REQUEST_DENIED") {
|
|
208
|
+
return {
|
|
209
|
+
inputId: "google_maps",
|
|
210
|
+
ok: false,
|
|
211
|
+
error: "Google Maps API key was rejected.",
|
|
212
|
+
fix: "Run: helm secrets set GOOGLE_MAPS_API_KEY with a valid key.",
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
return { inputId: "google_maps", ok: true, detail: "geocoding OK" };
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
219
|
+
return {
|
|
220
|
+
inputId: "google_maps",
|
|
221
|
+
ok: false,
|
|
222
|
+
error: `Google Maps test failed: ${msg}`,
|
|
223
|
+
fix: "Check your Maps API key and internet connection, then retry.",
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Tests the Todoist connection by fetching the authenticated user's info.
|
|
229
|
+
* Returns the user's display name on success.
|
|
230
|
+
*/
|
|
231
|
+
async function testTodoist(username) {
|
|
232
|
+
const apiToken = await getSecret(username, "TODOIST_API_TOKEN");
|
|
233
|
+
if (!apiToken) {
|
|
234
|
+
return {
|
|
235
|
+
inputId: "todoist",
|
|
236
|
+
ok: false,
|
|
237
|
+
error: "Todoist API token is missing.",
|
|
238
|
+
fix: "Run: helm secrets set TODOIST_API_TOKEN",
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
try {
|
|
242
|
+
const res = await fetch("https://api.todoist.com/rest/v2/user", {
|
|
243
|
+
headers: { Authorization: `Bearer ${apiToken}` },
|
|
244
|
+
});
|
|
245
|
+
if (res.status === 401) {
|
|
246
|
+
return {
|
|
247
|
+
inputId: "todoist",
|
|
248
|
+
ok: false,
|
|
249
|
+
error: "Todoist API token was rejected (401).",
|
|
250
|
+
fix: "Run: helm secrets set TODOIST_API_TOKEN with a fresh token from Todoist settings.",
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
if (!res.ok) {
|
|
254
|
+
return {
|
|
255
|
+
inputId: "todoist",
|
|
256
|
+
ok: false,
|
|
257
|
+
error: `Todoist API returned HTTP ${res.status}.`,
|
|
258
|
+
fix: "Check your Todoist API token and retry.",
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
const data = (await res.json());
|
|
262
|
+
return { inputId: "todoist", ok: true, detail: data.full_name };
|
|
263
|
+
}
|
|
264
|
+
catch (err) {
|
|
265
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
266
|
+
return {
|
|
267
|
+
inputId: "todoist",
|
|
268
|
+
ok: false,
|
|
269
|
+
error: `Todoist test failed: ${msg}`,
|
|
270
|
+
fix: "Check your Todoist API token and internet connection, then retry.",
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Tests the Zoom Server-to-Server OAuth connection by exchanging
|
|
276
|
+
* account credentials for an access token. A successful token
|
|
277
|
+
* exchange confirms the app credentials are valid.
|
|
278
|
+
*/
|
|
279
|
+
async function testZoom(username) {
|
|
280
|
+
const accountId = await getSecret(username, "ZOOM_ACCOUNT_ID");
|
|
281
|
+
const clientId = await getSecret(username, "ZOOM_CLIENT_ID");
|
|
282
|
+
const clientSecret = await getSecret(username, "ZOOM_CLIENT_SECRET");
|
|
283
|
+
if (!accountId || !clientId || !clientSecret) {
|
|
284
|
+
return {
|
|
285
|
+
inputId: "zoom",
|
|
286
|
+
ok: false,
|
|
287
|
+
error: "One or more Zoom credentials are missing.",
|
|
288
|
+
fix: "Run: helm secrets set ZOOM_ACCOUNT_ID && helm secrets set ZOOM_CLIENT_ID && helm secrets set ZOOM_CLIENT_SECRET",
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
try {
|
|
292
|
+
const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString("base64");
|
|
293
|
+
const url = new URL("https://zoom.us/oauth/token");
|
|
294
|
+
url.searchParams.set("grant_type", "account_credentials");
|
|
295
|
+
url.searchParams.set("account_id", accountId);
|
|
296
|
+
const res = await fetch(url.toString(), {
|
|
297
|
+
method: "POST",
|
|
298
|
+
headers: { Authorization: `Basic ${credentials}` },
|
|
299
|
+
});
|
|
300
|
+
if (res.status === 401) {
|
|
301
|
+
return {
|
|
302
|
+
inputId: "zoom",
|
|
303
|
+
ok: false,
|
|
304
|
+
error: "Zoom credentials were rejected (401).",
|
|
305
|
+
fix: "Verify your ZOOM_CLIENT_ID and ZOOM_CLIENT_SECRET in the Zoom Marketplace, then run helm secrets set for each.",
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
if (!res.ok) {
|
|
309
|
+
return {
|
|
310
|
+
inputId: "zoom",
|
|
311
|
+
ok: false,
|
|
312
|
+
error: `Zoom OAuth returned HTTP ${res.status}.`,
|
|
313
|
+
fix: "Check your Zoom Server-to-Server app configuration and retry.",
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
return { inputId: "zoom", ok: true, detail: "token exchange OK" };
|
|
317
|
+
}
|
|
318
|
+
catch (err) {
|
|
319
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
320
|
+
return {
|
|
321
|
+
inputId: "zoom",
|
|
322
|
+
ok: false,
|
|
323
|
+
error: `Zoom test failed: ${msg}`,
|
|
324
|
+
fix: "Check your Zoom credentials and internet connection, then retry.",
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
// ─── Dispatcher ───────────────────────────────────────────────────────────────
|
|
329
|
+
/**
|
|
330
|
+
* Runs the connectivity test for the given input ID.
|
|
331
|
+
*
|
|
332
|
+
* Returns an InputTestResult regardless of outcome — errors are
|
|
333
|
+
* represented in the result rather than thrown, so callers can
|
|
334
|
+
* display results for multiple inputs without short-circuiting.
|
|
335
|
+
*
|
|
336
|
+
* @param inputId - The input identifier to test (e.g. "gmail").
|
|
337
|
+
* @param username - Active username whose credentials to use.
|
|
338
|
+
*/
|
|
339
|
+
export async function testInput(inputId, username) {
|
|
340
|
+
switch (inputId) {
|
|
341
|
+
case "gmail":
|
|
342
|
+
return testGmail(username);
|
|
343
|
+
case "google_calendar":
|
|
344
|
+
return testGoogleCalendar(username);
|
|
345
|
+
case "google_maps":
|
|
346
|
+
return testGoogleMaps(username);
|
|
347
|
+
case "todoist":
|
|
348
|
+
return testTodoist(username);
|
|
349
|
+
case "zoom":
|
|
350
|
+
return testZoom(username);
|
|
351
|
+
default:
|
|
352
|
+
return {
|
|
353
|
+
inputId,
|
|
354
|
+
ok: false,
|
|
355
|
+
error: `No test implementation for input "${inputId}".`,
|
|
356
|
+
fix: `Add a test function for "${inputId}" in core/inputs.ts.`,
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
//# sourceMappingURL=inputs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inputs.js","sourceRoot":"","sources":["../../src/core/inputs.ts"],"names":[],"mappings":"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"}
|