gws-axi 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +91 -0
  3. package/dist/bin/gws-axi.d.ts +2 -0
  4. package/dist/bin/gws-axi.js +4 -0
  5. package/dist/bin/gws-axi.js.map +1 -0
  6. package/dist/src/auth/gcloud.d.ts +21 -0
  7. package/dist/src/auth/gcloud.js +134 -0
  8. package/dist/src/auth/gcloud.js.map +1 -0
  9. package/dist/src/auth/loopback.d.ts +50 -0
  10. package/dist/src/auth/loopback.js +420 -0
  11. package/dist/src/auth/loopback.js.map +1 -0
  12. package/dist/src/auth/pending.d.ts +15 -0
  13. package/dist/src/auth/pending.js +35 -0
  14. package/dist/src/auth/pending.js.map +1 -0
  15. package/dist/src/auth/scopes.d.ts +13 -0
  16. package/dist/src/auth/scopes.js +29 -0
  17. package/dist/src/auth/scopes.js.map +1 -0
  18. package/dist/src/auth/setup-html.d.ts +13 -0
  19. package/dist/src/auth/setup-html.js +245 -0
  20. package/dist/src/auth/setup-html.js.map +1 -0
  21. package/dist/src/auth/state.d.ts +4 -0
  22. package/dist/src/auth/state.js +41 -0
  23. package/dist/src/auth/state.js.map +1 -0
  24. package/dist/src/auth/steps.d.ts +30 -0
  25. package/dist/src/auth/steps.js +306 -0
  26. package/dist/src/auth/steps.js.map +1 -0
  27. package/dist/src/cli.d.ts +2 -0
  28. package/dist/src/cli.js +72 -0
  29. package/dist/src/cli.js.map +1 -0
  30. package/dist/src/commands/auth.d.ts +2 -0
  31. package/dist/src/commands/auth.js +453 -0
  32. package/dist/src/commands/auth.js.map +1 -0
  33. package/dist/src/commands/calendar/calendars.d.ts +2 -0
  34. package/dist/src/commands/calendar/calendars.js +98 -0
  35. package/dist/src/commands/calendar/calendars.js.map +1 -0
  36. package/dist/src/commands/calendar/events.d.ts +2 -0
  37. package/dist/src/commands/calendar/events.js +261 -0
  38. package/dist/src/commands/calendar/events.js.map +1 -0
  39. package/dist/src/commands/calendar/get.d.ts +2 -0
  40. package/dist/src/commands/calendar/get.js +176 -0
  41. package/dist/src/commands/calendar/get.js.map +1 -0
  42. package/dist/src/commands/calendar.d.ts +2 -0
  43. package/dist/src/commands/calendar.js +76 -0
  44. package/dist/src/commands/calendar.js.map +1 -0
  45. package/dist/src/commands/docs.d.ts +2 -0
  46. package/dist/src/commands/docs.js +19 -0
  47. package/dist/src/commands/docs.js.map +1 -0
  48. package/dist/src/commands/doctor.d.ts +2 -0
  49. package/dist/src/commands/doctor.js +213 -0
  50. package/dist/src/commands/doctor.js.map +1 -0
  51. package/dist/src/commands/drive.d.ts +2 -0
  52. package/dist/src/commands/drive.js +17 -0
  53. package/dist/src/commands/drive.js.map +1 -0
  54. package/dist/src/commands/gmail.d.ts +2 -0
  55. package/dist/src/commands/gmail.js +20 -0
  56. package/dist/src/commands/gmail.js.map +1 -0
  57. package/dist/src/commands/home.d.ts +1 -0
  58. package/dist/src/commands/home.js +42 -0
  59. package/dist/src/commands/home.js.map +1 -0
  60. package/dist/src/commands/service-stub.d.ts +8 -0
  61. package/dist/src/commands/service-stub.js +67 -0
  62. package/dist/src/commands/service-stub.js.map +1 -0
  63. package/dist/src/commands/slides.d.ts +2 -0
  64. package/dist/src/commands/slides.js +11 -0
  65. package/dist/src/commands/slides.js.map +1 -0
  66. package/dist/src/config.d.ts +46 -0
  67. package/dist/src/config.js +155 -0
  68. package/dist/src/config.js.map +1 -0
  69. package/dist/src/google/account.d.ts +12 -0
  70. package/dist/src/google/account.js +65 -0
  71. package/dist/src/google/account.js.map +1 -0
  72. package/dist/src/google/client.d.ts +29 -0
  73. package/dist/src/google/client.js +106 -0
  74. package/dist/src/google/client.js.map +1 -0
  75. package/dist/src/google/probe.d.ts +15 -0
  76. package/dist/src/google/probe.js +200 -0
  77. package/dist/src/google/probe.js.map +1 -0
  78. package/dist/src/google/tokens.d.ts +22 -0
  79. package/dist/src/google/tokens.js +91 -0
  80. package/dist/src/google/tokens.js.map +1 -0
  81. package/dist/src/output/index.d.ts +2 -0
  82. package/dist/src/output/index.js +3 -0
  83. package/dist/src/output/index.js.map +1 -0
  84. package/dist/src/output/render.d.ts +40 -0
  85. package/dist/src/output/render.js +65 -0
  86. package/dist/src/output/render.js.map +1 -0
  87. package/dist/src/output/schema.d.ts +32 -0
  88. package/dist/src/output/schema.js +69 -0
  89. package/dist/src/output/schema.js.map +1 -0
  90. package/package.json +61 -0
@@ -0,0 +1,420 @@
1
+ import { createHash, randomBytes } from "node:crypto";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { createServer, } from "node:http";
4
+ import { dirname } from "node:path";
5
+ import { URL } from "node:url";
6
+ import { credentialsPath, listAccounts, normalizeEmail, profilePathForAccount, setDefaultAccount, tokensPathForAccount, } from "../config.js";
7
+ import { markStepDone } from "./state.js";
8
+ import { allScopes } from "./scopes.js";
9
+ import { clearPendingAuth, isPendingAuthExpired, readPendingAuth, writePendingAuth, } from "./pending.js";
10
+ import { setupHtmlPath, writeSetupHtml } from "./setup-html.js";
11
+ function collapseHome(path) {
12
+ const home = process.env.HOME ?? "";
13
+ return home && path.startsWith(home) ? `~${path.slice(home.length)}` : path;
14
+ }
15
+ function readCredentials() {
16
+ if (!existsSync(credentialsPath()))
17
+ return null;
18
+ try {
19
+ const parsed = JSON.parse(readFileSync(credentialsPath(), "utf-8"));
20
+ return parsed.installed ?? null;
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ function base64url(input) {
27
+ return input
28
+ .toString("base64")
29
+ .replace(/\+/g, "-")
30
+ .replace(/\//g, "_")
31
+ .replace(/=+$/, "");
32
+ }
33
+ function pkcePair() {
34
+ const verifier = base64url(randomBytes(32));
35
+ const challenge = base64url(createHash("sha256").update(verifier).digest());
36
+ return { verifier, challenge };
37
+ }
38
+ function writeAccountFiles(email, tokens, profile) {
39
+ const tokensP = tokensPathForAccount(email);
40
+ const profileP = profilePathForAccount(email);
41
+ mkdirSync(dirname(tokensP), { recursive: true });
42
+ writeFileSync(tokensP, `${JSON.stringify(tokens, null, 2)}\n`, { mode: 0o600 });
43
+ writeFileSync(profileP, `${JSON.stringify(profile, null, 2)}\n`);
44
+ }
45
+ function buildAuthUrl(params) {
46
+ const u = new URL("https://accounts.google.com/o/oauth2/v2/auth");
47
+ u.searchParams.set("client_id", params.clientId);
48
+ u.searchParams.set("redirect_uri", params.redirectUri);
49
+ u.searchParams.set("response_type", "code");
50
+ u.searchParams.set("scope", params.scopes.join(" "));
51
+ u.searchParams.set("code_challenge", params.challenge);
52
+ u.searchParams.set("code_challenge_method", "S256");
53
+ u.searchParams.set("state", params.state);
54
+ u.searchParams.set("access_type", "offline");
55
+ u.searchParams.set("prompt", "consent");
56
+ // Deliberately NOT setting include_granted_scopes=true. That flag
57
+ // returns access tokens covering every scope the user has ever
58
+ // granted this OAuth client, not just the scopes we asked for now,
59
+ // which makes scope counts balloon unpredictably when the user has
60
+ // historical grants from testing / revocations / different scope
61
+ // configs. Since we always request the full scope set and force
62
+ // prompt=consent (so users re-approve every time), incremental
63
+ // authorization isn't buying us anything — each auth should be a
64
+ // clean grant matching exactly what we asked for.
65
+ if (params.loginHint) {
66
+ u.searchParams.set("login_hint", params.loginHint);
67
+ }
68
+ return u.toString();
69
+ }
70
+ async function exchangeCode(params) {
71
+ const body = new URLSearchParams({
72
+ client_id: params.clientId,
73
+ client_secret: params.clientSecret,
74
+ code: params.code,
75
+ redirect_uri: params.redirectUri,
76
+ grant_type: "authorization_code",
77
+ code_verifier: params.verifier,
78
+ });
79
+ const res = await fetch("https://oauth2.googleapis.com/token", {
80
+ method: "POST",
81
+ headers: { "content-type": "application/x-www-form-urlencoded" },
82
+ body,
83
+ });
84
+ if (!res.ok) {
85
+ const txt = await res.text();
86
+ throw new Error(`Token exchange failed (${res.status}): ${txt}`);
87
+ }
88
+ return (await res.json());
89
+ }
90
+ async function fetchUserinfo(accessToken) {
91
+ const res = await fetch("https://openidconnect.googleapis.com/v1/userinfo", {
92
+ headers: { authorization: `Bearer ${accessToken}` },
93
+ });
94
+ if (!res.ok) {
95
+ throw new Error(`userinfo failed (${res.status})`);
96
+ }
97
+ return (await res.json());
98
+ }
99
+ async function waitForCallback(server, expectedState) {
100
+ return new Promise((resolve, reject) => {
101
+ const timeout = setTimeout(() => {
102
+ reject(new Error("Timed out waiting for OAuth callback after 5 minutes"));
103
+ }, 5 * 60_000);
104
+ server.on("request", (req, res) => {
105
+ if (!req.url)
106
+ return;
107
+ const u = new URL(req.url, "http://127.0.0.1");
108
+ if (u.pathname !== "/callback") {
109
+ res.statusCode = 404;
110
+ res.end("Not found");
111
+ return;
112
+ }
113
+ const code = u.searchParams.get("code");
114
+ const state = u.searchParams.get("state");
115
+ const errorParam = u.searchParams.get("error");
116
+ res.statusCode = 200;
117
+ res.setHeader("content-type", "text/html; charset=utf-8");
118
+ if (errorParam) {
119
+ res.end(errorPage(errorParam));
120
+ clearTimeout(timeout);
121
+ reject(new Error(`OAuth error: ${errorParam}`));
122
+ return;
123
+ }
124
+ if (!code || state !== expectedState) {
125
+ res.end(errorPage("invalid_state_or_missing_code"));
126
+ clearTimeout(timeout);
127
+ reject(new Error("OAuth callback missing code or state mismatch"));
128
+ return;
129
+ }
130
+ res.end(successPage());
131
+ clearTimeout(timeout);
132
+ resolve({ code, scope: u.searchParams.get("scope") ?? undefined });
133
+ });
134
+ });
135
+ }
136
+ function successPage() {
137
+ return `<!doctype html>
138
+ <html><head><meta charset="utf-8"><title>gws-axi — authenticated</title>
139
+ <style>body{font-family:-apple-system,system-ui,sans-serif;max-width:480px;margin:60px auto;padding:24px;color:#222}h1{color:#1a7f37}</style>
140
+ </head><body><h1>Authenticated</h1><p>You can close this tab and return to your terminal.</p></body></html>`;
141
+ }
142
+ function errorPage(message) {
143
+ const escaped = message.replace(/[<>&]/g, (c) => ({ "<": "&lt;", ">": "&gt;", "&": "&amp;" })[c] ?? c);
144
+ return `<!doctype html>
145
+ <html><head><meta charset="utf-8"><title>gws-axi — error</title>
146
+ <style>body{font-family:-apple-system,system-ui,sans-serif;max-width:480px;margin:60px auto;padding:24px;color:#222}h1{color:#c62828}pre{background:#f4f4f4;padding:12px;border-radius:4px}</style>
147
+ </head><body><h1>Authentication failed</h1><pre>${escaped}</pre><p>Close this tab and check the terminal.</p></body></html>`;
148
+ }
149
+ /**
150
+ * Reserve a port by binding and immediately closing. The returned port is
151
+ * likely still free when the caller uses it, but not guaranteed — there's
152
+ * a microscopic race window. In practice it's not an issue.
153
+ */
154
+ async function reservePort() {
155
+ const server = createServer();
156
+ await new Promise((resolve, reject) => {
157
+ server.once("error", reject);
158
+ server.listen(0, "127.0.0.1", () => resolve());
159
+ });
160
+ const port = server.address().port;
161
+ await new Promise((resolve) => server.close(() => resolve()));
162
+ return port;
163
+ }
164
+ /**
165
+ * Phase 1: generate the auth URL, reserve a port, persist pending state,
166
+ * write setup.html with the authenticate button. Returns immediately so the
167
+ * agent can relay instructions to the user BEFORE any process blocks on a
168
+ * callback. Call `awaitPendingAuth` after instructing the user.
169
+ */
170
+ export async function preparePendingAuth(options = {}) {
171
+ const creds = readCredentials();
172
+ if (!creds) {
173
+ return {
174
+ error: "credentials.json missing — complete setup steps 1-4 first",
175
+ code: "PRECONDITION_FAILED",
176
+ };
177
+ }
178
+ // Clear any stale pending state from a previous abandoned run so the HTML
179
+ // helper doesn't show two conflicting banners and so a future --wait
180
+ // doesn't pick up the wrong pending.
181
+ clearPendingAuth();
182
+ const port = await reservePort();
183
+ const redirectUri = `http://127.0.0.1:${port}/callback`;
184
+ const { verifier, challenge } = pkcePair();
185
+ const state = base64url(randomBytes(16));
186
+ const scopes = allScopes();
187
+ const authUrl = buildAuthUrl({
188
+ clientId: creds.client_id,
189
+ redirectUri,
190
+ scopes,
191
+ challenge,
192
+ state,
193
+ loginHint: options.expectedAccount,
194
+ });
195
+ const now = new Date();
196
+ const expiresAt = new Date(now.getTime() + 10 * 60_000); // 10 min — plenty for user + agent coordination
197
+ const pending = {
198
+ version: 1,
199
+ url: authUrl,
200
+ port,
201
+ verifier,
202
+ state,
203
+ expected_account: options.expectedAccount,
204
+ started_at: now.toISOString(),
205
+ expires_at: expiresAt.toISOString(),
206
+ };
207
+ writePendingAuth(pending);
208
+ writeSetupHtml({
209
+ pendingAuth: { url: authUrl, account: options.expectedAccount },
210
+ });
211
+ return {
212
+ pending,
213
+ htmlPath: setupHtmlPath(),
214
+ credentialsPresent: true,
215
+ };
216
+ }
217
+ /**
218
+ * Phase 2: read pending state, start the callback server, block until the
219
+ * user authenticates (or timeout). Runs the token exchange, fetches the
220
+ * userinfo to identify the account, writes tokens + profile, updates
221
+ * default account if first, regenerates setup.html without the banner.
222
+ */
223
+ export async function awaitPendingAuth() {
224
+ const step = "tokens_obtained";
225
+ const pending = readPendingAuth();
226
+ if (!pending) {
227
+ return {
228
+ step,
229
+ advanced: false,
230
+ title: "No pending authentication",
231
+ error: "No pending auth flow — run `gws-axi auth login --account <email>` first to prepare",
232
+ code: "NO_PENDING_AUTH",
233
+ instructions: [
234
+ "Run `gws-axi auth login --account <email>` to prepare",
235
+ "Then run `gws-axi auth login --wait` to block on the user's browser click",
236
+ ],
237
+ };
238
+ }
239
+ if (isPendingAuthExpired(pending)) {
240
+ clearPendingAuth();
241
+ return {
242
+ step,
243
+ advanced: false,
244
+ title: "Pending authentication expired",
245
+ error: "The prepared OAuth flow expired — prepare a new one",
246
+ code: "PENDING_EXPIRED",
247
+ instructions: [
248
+ "Re-run `gws-axi auth login --account <email>` to prepare a fresh flow",
249
+ ],
250
+ };
251
+ }
252
+ const creds = readCredentials();
253
+ if (!creds) {
254
+ return {
255
+ step,
256
+ advanced: false,
257
+ title: "Credentials disappeared",
258
+ error: "credentials.json is missing — was it deleted between prepare and wait?",
259
+ code: "PRECONDITION_FAILED",
260
+ instructions: ["Re-run `gws-axi auth setup --credentials-json <path>`"],
261
+ };
262
+ }
263
+ const server = createServer();
264
+ try {
265
+ await new Promise((resolve, reject) => {
266
+ server.once("error", reject);
267
+ server.listen(pending.port, "127.0.0.1", () => resolve());
268
+ });
269
+ }
270
+ catch (err) {
271
+ return {
272
+ step,
273
+ advanced: false,
274
+ title: "Could not bind callback server",
275
+ error: `Port ${pending.port} is not available: ${err instanceof Error ? err.message : String(err)}`,
276
+ code: "PORT_UNAVAILABLE",
277
+ instructions: [
278
+ "Another process is bound to that port. Retry with a fresh flow:",
279
+ "Run `gws-axi auth login --account <email>` again",
280
+ ],
281
+ };
282
+ }
283
+ const redirectUri = `http://127.0.0.1:${pending.port}/callback`;
284
+ // Snapshot account list BEFORE writing new tokens so we can detect
285
+ // whether this is the first-ever account (should be promoted to
286
+ // default) vs. an additional one (default stays put).
287
+ const accountsBefore = listAccounts();
288
+ try {
289
+ const { code, scope } = await waitForCallback(server, pending.state);
290
+ const tokens = await exchangeCode({
291
+ clientId: creds.client_id,
292
+ clientSecret: creds.client_secret,
293
+ code,
294
+ redirectUri,
295
+ verifier: pending.verifier,
296
+ });
297
+ const userinfo = await fetchUserinfo(tokens.access_token);
298
+ const authenticatedEmail = normalizeEmail(userinfo.email);
299
+ if (pending.expected_account &&
300
+ normalizeEmail(pending.expected_account) !== authenticatedEmail) {
301
+ return {
302
+ step,
303
+ advanced: false,
304
+ title: "Authenticated account does not match expected",
305
+ error: `Expected ${pending.expected_account}, got ${authenticatedEmail}`,
306
+ code: "ACCOUNT_MISMATCH",
307
+ instructions: [
308
+ `Re-run with: \`gws-axi auth login --account ${pending.expected_account}\``,
309
+ "Make sure you sign in as the correct account in the browser",
310
+ ],
311
+ };
312
+ }
313
+ const grantedScopes = (scope ?? tokens.scope).split(" ").filter(Boolean);
314
+ const stored = {
315
+ client_id: creds.client_id,
316
+ access_token: tokens.access_token,
317
+ refresh_token: tokens.refresh_token,
318
+ expiry_date: Date.now() + tokens.expires_in * 1000,
319
+ scope: grantedScopes.join(" "),
320
+ token_type: tokens.token_type,
321
+ obtained_at: new Date().toISOString(),
322
+ };
323
+ const profile = {
324
+ email: authenticatedEmail,
325
+ verified_email: userinfo.email_verified,
326
+ name: userinfo.name,
327
+ picture: userinfo.picture,
328
+ sub: userinfo.sub,
329
+ updated_at: new Date().toISOString(),
330
+ };
331
+ writeAccountFiles(authenticatedEmail, stored, profile);
332
+ // Only promote to default if there were no accounts BEFORE this one.
333
+ // getDefaultAccount()'s implicit single-account fallback can return
334
+ // undefined for a newly-added second account (no explicit default
335
+ // in config.json because the first account was implicitly inferred
336
+ // via listAccounts().length === 1), which would wrongly overwrite
337
+ // the existing default. Always persist an explicit default_account
338
+ // on first auth so subsequent auths don't disturb it.
339
+ if (accountsBefore.length === 0) {
340
+ setDefaultAccount(authenticatedEmail);
341
+ }
342
+ markStepDone(step, {
343
+ accounts: listAccounts(),
344
+ latest_account: authenticatedEmail,
345
+ });
346
+ return {
347
+ step,
348
+ advanced: true,
349
+ title: "Tokens obtained",
350
+ detail: {
351
+ account: authenticatedEmail,
352
+ scopes_granted: grantedScopes.length,
353
+ scopes_requested: allScopes().length,
354
+ tokens_path: tokensPathForAccount(authenticatedEmail),
355
+ },
356
+ };
357
+ }
358
+ catch (err) {
359
+ return {
360
+ step,
361
+ advanced: false,
362
+ title: "OAuth flow failed",
363
+ error: err instanceof Error ? err.message : String(err),
364
+ code: "OAUTH_FAILED",
365
+ instructions: [
366
+ "Check that the consent screen (step 5) and test user (step 6) are configured",
367
+ "Re-run: `gws-axi auth login --account <email>` to start a fresh flow",
368
+ ],
369
+ };
370
+ }
371
+ finally {
372
+ // The browser holds a keep-alive connection to the callback server
373
+ // after the success/error page renders. server.close() alone only
374
+ // stops *new* connections — the lingering keep-alive keeps Node's
375
+ // event loop alive indefinitely. closeAllConnections() forcibly
376
+ // terminates them so the process exits immediately.
377
+ server.closeAllConnections();
378
+ server.close();
379
+ clearPendingAuth();
380
+ try {
381
+ writeSetupHtml();
382
+ }
383
+ catch {
384
+ // non-fatal
385
+ }
386
+ }
387
+ }
388
+ /**
389
+ * Helper for callers (like `auth setup`) that want to expose the prepared
390
+ * instructions to the user/agent as a StepOutcome. Does NOT block — just
391
+ * wraps preparePendingAuth into the StepOutcome shape.
392
+ */
393
+ export async function advanceTokensObtained(options = {}) {
394
+ const step = "tokens_obtained";
395
+ const prepared = await preparePendingAuth(options);
396
+ if ("error" in prepared) {
397
+ return {
398
+ step,
399
+ advanced: false,
400
+ title: prepared.code === "PRECONDITION_FAILED"
401
+ ? "OAuth credentials not yet saved"
402
+ : "OAuth prepare failed",
403
+ error: prepared.error,
404
+ code: prepared.code,
405
+ instructions: ["Re-run: `gws-axi auth setup --credentials-json <path>`"],
406
+ };
407
+ }
408
+ const expected = prepared.pending.expected_account;
409
+ return {
410
+ step,
411
+ advanced: false,
412
+ title: "Step 7 of 7: Authenticate in your browser",
413
+ instructions: [
414
+ `The gws-axi setup page (${collapseHome(prepared.htmlPath)}) must be open in the browser PROFILE/SESSION where the user is signed into ${expected ? `\`${expected}\`` : "the target Google account"}. If initial setup ran in a different browser profile, tell the user to open ${collapseHome(prepared.htmlPath)} in the correct profile first.`,
415
+ `In that setup page, the user waits for the yellow "Authenticate with Google" button (up to 10s auto-refresh), clicks it${expected ? `, signs in as \`${expected}\`` : ""}, approves scopes, and sees a success page.`,
416
+ "After RELAYING these instructions to the user, IMMEDIATELY run `gws-axi auth login --wait` in a new bash turn — do NOT wait for the user to confirm they're ready. The callback server must be listening BEFORE the user clicks. If you delay, the click hits an unreachable localhost URL. The wait is harmless: it just listens for up to 5 min while the user takes their time.",
417
+ ],
418
+ };
419
+ }
420
+ //# sourceMappingURL=loopback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopback.js","sourceRoot":"","sources":["../../../src/auth/loopback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface PendingAuth {
2
+ version: 1;
3
+ url: string;
4
+ port: number;
5
+ verifier: string;
6
+ state: string;
7
+ expected_account?: string;
8
+ started_at: string;
9
+ expires_at: string;
10
+ }
11
+ export declare function pendingAuthPath(): string;
12
+ export declare function readPendingAuth(): PendingAuth | null;
13
+ export declare function writePendingAuth(pending: PendingAuth): void;
14
+ export declare function clearPendingAuth(): void;
15
+ export declare function isPendingAuthExpired(pending: PendingAuth): boolean;
@@ -0,0 +1,35 @@
1
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { configDir } from "../config.js";
4
+ export function pendingAuthPath() {
5
+ return join(configDir(), "pending-auth.json");
6
+ }
7
+ export function readPendingAuth() {
8
+ const path = pendingAuthPath();
9
+ if (!existsSync(path))
10
+ return null;
11
+ try {
12
+ const parsed = JSON.parse(readFileSync(path, "utf-8"));
13
+ if (parsed.version !== 1)
14
+ return null;
15
+ return parsed;
16
+ }
17
+ catch {
18
+ return null;
19
+ }
20
+ }
21
+ export function writePendingAuth(pending) {
22
+ const path = pendingAuthPath();
23
+ mkdirSync(dirname(path), { recursive: true });
24
+ writeFileSync(path, `${JSON.stringify(pending, null, 2)}\n`, { mode: 0o600 });
25
+ }
26
+ export function clearPendingAuth() {
27
+ const path = pendingAuthPath();
28
+ if (existsSync(path)) {
29
+ rmSync(path, { force: true });
30
+ }
31
+ }
32
+ export function isPendingAuthExpired(pending) {
33
+ return Date.parse(pending.expires_at) < Date.now();
34
+ }
35
+ //# sourceMappingURL=pending.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending.js","sourceRoot":"","sources":["../../../src/auth/pending.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAazC,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,mBAAmB,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAgB,CAAC;QACtE,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACtC,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAoB;IACnD,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,aAAa,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,MAAM,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAoB;IACvD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AACrD,CAAC"}
@@ -0,0 +1,13 @@
1
+ export declare const BASE_SCOPES: readonly ["openid", "email", "profile"];
2
+ export declare const SERVICE_SCOPES: {
3
+ readonly gmail: "https://www.googleapis.com/auth/gmail.modify";
4
+ readonly calendar: "https://www.googleapis.com/auth/calendar";
5
+ readonly docs: "https://www.googleapis.com/auth/documents";
6
+ readonly drive: "https://www.googleapis.com/auth/drive";
7
+ readonly slides: "https://www.googleapis.com/auth/presentations";
8
+ };
9
+ export type ServiceName = keyof typeof SERVICE_SCOPES;
10
+ export declare const SERVICES: ServiceName[];
11
+ export declare const REQUIRED_APIS: Record<ServiceName, string>;
12
+ export declare function allScopes(): string[];
13
+ export declare function allApis(): string[];
@@ -0,0 +1,29 @@
1
+ export const BASE_SCOPES = ["openid", "email", "profile"];
2
+ export const SERVICE_SCOPES = {
3
+ gmail: "https://www.googleapis.com/auth/gmail.modify",
4
+ calendar: "https://www.googleapis.com/auth/calendar",
5
+ docs: "https://www.googleapis.com/auth/documents",
6
+ drive: "https://www.googleapis.com/auth/drive",
7
+ slides: "https://www.googleapis.com/auth/presentations",
8
+ };
9
+ export const SERVICES = [
10
+ "gmail",
11
+ "calendar",
12
+ "docs",
13
+ "drive",
14
+ "slides",
15
+ ];
16
+ export const REQUIRED_APIS = {
17
+ gmail: "gmail.googleapis.com",
18
+ calendar: "calendar-json.googleapis.com",
19
+ docs: "docs.googleapis.com",
20
+ drive: "drive.googleapis.com",
21
+ slides: "slides.googleapis.com",
22
+ };
23
+ export function allScopes() {
24
+ return [...BASE_SCOPES, ...Object.values(SERVICE_SCOPES)];
25
+ }
26
+ export function allApis() {
27
+ return Object.values(REQUIRED_APIS);
28
+ }
29
+ //# sourceMappingURL=scopes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scopes.js","sourceRoot":"","sources":["../../../src/auth/scopes.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAU,CAAC;AAEnE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,KAAK,EAAE,8CAA8C;IACrD,QAAQ,EAAE,0CAA0C;IACpD,IAAI,EAAE,2CAA2C;IACjD,KAAK,EAAE,uCAAuC;IAC9C,MAAM,EAAE,+CAA+C;CAC/C,CAAC;AAIX,MAAM,CAAC,MAAM,QAAQ,GAAkB;IACrC,OAAO;IACP,UAAU;IACV,MAAM;IACN,OAAO;IACP,QAAQ;CACT,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAgC;IACxD,KAAK,EAAE,sBAAsB;IAC7B,QAAQ,EAAE,8BAA8B;IACxC,IAAI,EAAE,qBAAqB;IAC3B,KAAK,EAAE,sBAAsB;IAC7B,MAAM,EAAE,uBAAuB;CAChC,CAAC;AAEF,MAAM,UAAU,SAAS;IACvB,OAAO,CAAC,GAAG,WAAW,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,OAAO,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,13 @@
1
+ export declare function setupHtmlPath(): string;
2
+ export interface SetupHtmlOptions {
3
+ /**
4
+ * When set, render a prominent "Authenticate now" button at the top of
5
+ * setup.html pointing at this URL. Used by the OAuth loopback flow to
6
+ * avoid printing the jumbo URL to the terminal (where it gets mangled).
7
+ */
8
+ pendingAuth?: {
9
+ url: string;
10
+ account?: string;
11
+ };
12
+ }
13
+ export declare function writeSetupHtml(options?: SetupHtmlOptions): string;