zele 0.2.0 → 0.3.5
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 +38 -1
- package/bin/zele +27 -0
- package/dist/api-utils.d.ts +51 -2
- package/dist/api-utils.js +89 -3
- package/dist/api-utils.js.map +1 -1
- package/dist/auth.d.ts +27 -6
- package/dist/auth.js +185 -129
- package/dist/auth.js.map +1 -1
- package/dist/calendar-client.d.ts +16 -9
- package/dist/calendar-client.js +163 -59
- package/dist/calendar-client.js.map +1 -1
- package/dist/cli.js +28 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/attachment.js +17 -15
- package/dist/commands/attachment.js.map +1 -1
- package/dist/commands/auth-cmd.js +20 -9
- package/dist/commands/auth-cmd.js.map +1 -1
- package/dist/commands/calendar.js +67 -78
- package/dist/commands/calendar.js.map +1 -1
- package/dist/commands/draft.js +25 -18
- package/dist/commands/draft.js.map +1 -1
- package/dist/commands/label.js +33 -45
- package/dist/commands/label.js.map +1 -1
- package/dist/commands/mail-actions.js +11 -13
- package/dist/commands/mail-actions.js.map +1 -1
- package/dist/commands/mail.js +114 -128
- package/dist/commands/mail.js.map +1 -1
- package/dist/commands/profile.js +18 -21
- package/dist/commands/profile.js.map +1 -1
- package/dist/commands/watch.d.ts +2 -0
- package/dist/commands/watch.js +73 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/db.js +12 -13
- package/dist/db.js.map +1 -1
- package/dist/generated/browser.d.ts +12 -27
- package/dist/generated/client.d.ts +13 -28
- package/dist/generated/client.js +1 -1
- package/dist/generated/commonInputTypes.d.ts +90 -26
- package/dist/generated/enums.d.ts +0 -4
- package/dist/generated/enums.js +0 -3
- package/dist/generated/enums.js.map +1 -1
- package/dist/generated/internal/class.d.ts +22 -55
- package/dist/generated/internal/class.js +12 -4
- package/dist/generated/internal/class.js.map +1 -1
- package/dist/generated/internal/prismaNamespace.d.ts +272 -511
- package/dist/generated/internal/prismaNamespace.js +54 -66
- package/dist/generated/internal/prismaNamespace.js.map +1 -1
- package/dist/generated/internal/prismaNamespaceBrowser.d.ts +60 -74
- package/dist/generated/internal/prismaNamespaceBrowser.js +50 -62
- package/dist/generated/internal/prismaNamespaceBrowser.js.map +1 -1
- package/dist/generated/models/Account.d.ts +1637 -0
- package/dist/generated/models/Account.js +2 -0
- package/dist/generated/models/Account.js.map +1 -0
- package/dist/generated/models/CalendarList.d.ts +1161 -0
- package/dist/generated/models/CalendarList.js +2 -0
- package/dist/generated/models/CalendarList.js.map +1 -0
- package/dist/generated/models/Label.d.ts +1161 -0
- package/dist/generated/models/Label.js +2 -0
- package/dist/generated/models/Label.js.map +1 -0
- package/dist/generated/models/Profile.d.ts +1269 -0
- package/dist/generated/models/Profile.js +2 -0
- package/dist/generated/models/Profile.js.map +1 -0
- package/dist/generated/models/SyncState.d.ts +1130 -0
- package/dist/generated/models/SyncState.js +2 -0
- package/dist/generated/models/SyncState.js.map +1 -0
- package/dist/generated/models/Thread.d.ts +1608 -0
- package/dist/generated/models/Thread.js +2 -0
- package/dist/generated/models/Thread.js.map +1 -0
- package/dist/generated/models.d.ts +6 -9
- package/dist/gmail-client.d.ts +119 -94
- package/dist/gmail-client.js +862 -315
- package/dist/gmail-client.js.map +1 -1
- package/dist/mail-tui.d.ts +1 -0
- package/dist/mail-tui.js +517 -0
- package/dist/mail-tui.js.map +1 -0
- package/dist/output.d.ts +6 -4
- package/dist/output.js +124 -17
- package/dist/output.js.map +1 -1
- package/package.json +39 -11
- package/schema.prisma +81 -113
- package/src/api-utils.ts +103 -5
- package/src/auth.ts +224 -143
- package/src/calendar-client.ts +196 -89
- package/src/cli.ts +32 -1
- package/src/commands/attachment.ts +18 -19
- package/src/commands/auth-cmd.ts +19 -9
- package/src/commands/calendar.ts +42 -85
- package/src/commands/draft.ts +19 -22
- package/src/commands/label.ts +21 -57
- package/src/commands/mail-actions.ts +11 -19
- package/src/commands/mail.ts +104 -149
- package/src/commands/profile.ts +12 -28
- package/src/commands/watch.ts +88 -0
- package/src/db.ts +13 -16
- package/src/generated/browser.ts +49 -0
- package/src/generated/client.ts +71 -0
- package/src/generated/commonInputTypes.ts +332 -0
- package/src/generated/enums.ts +17 -0
- package/src/generated/internal/class.ts +250 -0
- package/src/generated/internal/prismaNamespace.ts +1198 -0
- package/src/generated/internal/prismaNamespaceBrowser.ts +169 -0
- package/src/generated/models/Account.ts +1848 -0
- package/src/generated/models/CalendarList.ts +1331 -0
- package/src/generated/models/Label.ts +1331 -0
- package/src/generated/models/Profile.ts +1439 -0
- package/src/generated/models/SyncState.ts +1300 -0
- package/src/generated/models/Thread.ts +1787 -0
- package/src/generated/models.ts +17 -0
- package/src/gmail-client.test.ts +59 -0
- package/src/gmail-client.ts +1034 -422
- package/src/mail-tui.tsx +1061 -0
- package/src/output.test.ts +1093 -0
- package/src/output.ts +128 -20
- package/src/schema.sql +58 -68
- package/src/test-fixtures/email-html/safe-claude-event.html +28 -0
- package/src/test-fixtures/email-html/safe-product-announcement.html +25 -0
- package/src/test-fixtures/email-html/safe-tracked-links.html +27 -0
- package/src/test-fixtures/email-html-snapshots/safe-claude-event.html.md +9 -0
- package/src/test-fixtures/email-html-snapshots/safe-product-announcement.html.md +13 -0
- package/src/test-fixtures/email-html-snapshots/safe-tracked-links.html.md +7 -0
- package/AGENTS.md +0 -26
- package/CHANGELOG.md +0 -36
- package/dist/generated/models/accounts.d.ts +0 -2000
- package/dist/generated/models/accounts.js +0 -2
- package/dist/generated/models/accounts.js.map +0 -1
- package/dist/generated/models/calendar_events.d.ts +0 -1433
- package/dist/generated/models/calendar_events.js +0 -2
- package/dist/generated/models/calendar_events.js.map +0 -1
- package/dist/generated/models/calendar_lists.d.ts +0 -1131
- package/dist/generated/models/calendar_lists.js +0 -2
- package/dist/generated/models/calendar_lists.js.map +0 -1
- package/dist/generated/models/label_counts.d.ts +0 -1131
- package/dist/generated/models/label_counts.js +0 -2
- package/dist/generated/models/label_counts.js.map +0 -1
- package/dist/generated/models/labels.d.ts +0 -1131
- package/dist/generated/models/labels.js +0 -2
- package/dist/generated/models/labels.js.map +0 -1
- package/dist/generated/models/profiles.d.ts +0 -1131
- package/dist/generated/models/profiles.js +0 -2
- package/dist/generated/models/profiles.js.map +0 -1
- package/dist/generated/models/sync_states.d.ts +0 -1107
- package/dist/generated/models/sync_states.js +0 -2
- package/dist/generated/models/sync_states.js.map +0 -1
- package/dist/generated/models/thread_lists.d.ts +0 -1404
- package/dist/generated/models/thread_lists.js +0 -2
- package/dist/generated/models/thread_lists.js.map +0 -1
- package/dist/generated/models/threads.d.ts +0 -1247
- package/dist/generated/models/threads.js +0 -2
- package/dist/generated/models/threads.js.map +0 -1
- package/dist/gmail-cache.d.ts +0 -60
- package/dist/gmail-cache.js +0 -264
- package/dist/gmail-cache.js.map +0 -1
- package/docs/gogcli-gmail-implementation.md +0 -599
- package/scripts/test-device-code-clients.ts +0 -186
- package/scripts/test-micropython-scopes.ts +0 -72
- package/scripts/test-oauth-clients.ts +0 -257
- package/src/gmail-cache.ts +0 -339
- package/tsconfig.json +0 -16
package/README.md
CHANGED
|
@@ -39,6 +39,7 @@ zele mail read <thread-id> # read a thread
|
|
|
39
39
|
zele mail send # send an email
|
|
40
40
|
zele mail reply <thread-id> # reply to a thread
|
|
41
41
|
zele mail forward <thread-id> # forward a thread
|
|
42
|
+
zele mail watch # watch for new emails (poll)
|
|
42
43
|
```
|
|
43
44
|
|
|
44
45
|
### Mail actions
|
|
@@ -55,6 +56,42 @@ zele mail label <thread-id>
|
|
|
55
56
|
zele mail trash-spam
|
|
56
57
|
```
|
|
57
58
|
|
|
59
|
+
### Search query syntax
|
|
60
|
+
|
|
61
|
+
`mail search` and `mail watch --query` use [Gmail search operators](https://support.google.com/mail/answer/7190). `mail search` sends the query server-side (full Gmail support), while `mail watch --query` evaluates a subset client-side.
|
|
62
|
+
|
|
63
|
+
| Operator | Example | Description |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| `from:` | `from:github` | Messages from a sender |
|
|
66
|
+
| `to:` | `to:me@example.com` | Messages sent to a recipient |
|
|
67
|
+
| `cc:` | `cc:team@example.com` | Messages where recipient was CC'd |
|
|
68
|
+
| `subject:` | `subject:invoice` | Messages with words in the subject |
|
|
69
|
+
| `is:unread` | `is:unread` | Unread messages |
|
|
70
|
+
| `is:read` | `is:read` | Read messages |
|
|
71
|
+
| `is:starred` | `is:starred` | Starred messages |
|
|
72
|
+
| `has:attachment` | `has:attachment` | Messages with attachments (heuristic in watch) |
|
|
73
|
+
| `-` (negate) | `-from:noreply` | Exclude matching messages |
|
|
74
|
+
| `" "` (quotes) | `"exact phrase"` | Match an exact phrase |
|
|
75
|
+
| `label:` | `label:work` | Messages with a specific label (search only) |
|
|
76
|
+
| `in:` | `in:sent` | Messages in a folder (search only) |
|
|
77
|
+
| `after:` | `after:2024/01/01` | Messages after a date (search only) |
|
|
78
|
+
| `before:` | `before:2024/12/31` | Messages before a date (search only) |
|
|
79
|
+
| `newer_than:` | `newer_than:7d` | Messages newer than a period (search only) |
|
|
80
|
+
| `older_than:` | `older_than:1m` | Messages older than a period (search only) |
|
|
81
|
+
| `filename:` | `filename:pdf` | Attachment filename (search only) |
|
|
82
|
+
| `size:` / `larger:` / `smaller:` | `larger:5M` | Filter by message size (search only) |
|
|
83
|
+
| `OR` | `from:a OR from:b` | Match either term (search only) |
|
|
84
|
+
| `{ }` | `{from:a from:b}` | Group OR terms (search only) |
|
|
85
|
+
|
|
86
|
+
Combine multiple operators to narrow results:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
zele mail search "from:github is:unread newer_than:7d"
|
|
90
|
+
zele mail watch --query "from:github has:attachment"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Operators marked **(search only)** are handled server-side by Gmail and only available in `mail search`. Using them in `mail watch --query` prints a warning and skips the operator.
|
|
94
|
+
|
|
58
95
|
### Drafts
|
|
59
96
|
|
|
60
97
|
```bash
|
|
@@ -89,7 +126,7 @@ zele cal freebusy # check availability
|
|
|
89
126
|
### Attachments
|
|
90
127
|
|
|
91
128
|
```bash
|
|
92
|
-
zele attachment list <
|
|
129
|
+
zele attachment list <thread-id>
|
|
93
130
|
zele attachment get <message-id> <attachment-id>
|
|
94
131
|
```
|
|
95
132
|
|
package/bin/zele
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
# Shell launcher for zele CLI.
|
|
3
|
+
# Prefers bun (required for the TUI), falls back to node for non-TUI commands.
|
|
4
|
+
# Uses exec so no child process is spawned — the shell is replaced in-place.
|
|
5
|
+
#
|
|
6
|
+
# Shebang uses "#!/usr/bin/env sh" instead of "#!/bin/sh" so that npm's
|
|
7
|
+
# cmd-shim on Windows captures "sh" as the program name (looked up via PATH)
|
|
8
|
+
# rather than the literal "/bin/sh" path which doesn't exist on Windows.
|
|
9
|
+
# Git for Windows provides sh.exe on PATH, making this work cross-platform.
|
|
10
|
+
|
|
11
|
+
# Resolve symlink (npm/pnpm create symlinks for bin entries)
|
|
12
|
+
SELF="$0"
|
|
13
|
+
if [ -L "$SELF" ]; then
|
|
14
|
+
LINK="$(readlink "$SELF")"
|
|
15
|
+
case "$LINK" in
|
|
16
|
+
/*) SELF="$LINK" ;;
|
|
17
|
+
*) SELF="$(dirname "$SELF")/$LINK" ;;
|
|
18
|
+
esac
|
|
19
|
+
fi
|
|
20
|
+
DIR="$(cd "$(dirname "$SELF")" && pwd)"
|
|
21
|
+
CLI="$DIR/../dist/cli.js"
|
|
22
|
+
|
|
23
|
+
if command -v bun >/dev/null 2>&1; then
|
|
24
|
+
exec bun "$CLI" "$@"
|
|
25
|
+
else
|
|
26
|
+
exec node "$CLI" "$@"
|
|
27
|
+
fi
|
package/dist/api-utils.d.ts
CHANGED
|
@@ -1,6 +1,55 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import * as errore from 'errore';
|
|
2
|
+
/** Exclude Error subtypes from a union. Used by mapConcurrent to strip
|
|
3
|
+
* error return types from the success array — errors are returned separately. */
|
|
4
|
+
type ExcludeError<T> = T extends Error ? never : T;
|
|
5
|
+
/** Extract Error subtypes from a union. Used by mapConcurrent for the error branch. */
|
|
6
|
+
type ExtractError<T> = T extends Error ? T : never;
|
|
7
|
+
type Falsy = false | 0 | '' | null | undefined;
|
|
8
|
+
/** Generic truthy type guard for Array.filter() chains.
|
|
9
|
+
* Useful to drop null/undefined placeholders while preserving inferred item types. */
|
|
10
|
+
export declare function isTruthy<T>(value: T): value is Exclude<T, Falsy>;
|
|
11
|
+
/** Run promises with bounded concurrency.
|
|
12
|
+
* Error-aware: if any callback returns an Error instance, remaining work is
|
|
13
|
+
* aborted and that error is returned as a value (no throwing needed).
|
|
14
|
+
* Callbacks should return Error for fatal failures (auth) and null for skip.
|
|
15
|
+
* The success array is typed without Error — errors are only in the Error branch. */
|
|
16
|
+
export declare function mapConcurrent<T, R>(items: T[], fn: (item: T) => Promise<R>, concurrency?: number): Promise<ExcludeError<R>[] | ExtractError<R>>;
|
|
3
17
|
/** Simple retry for rate limit errors (429 and 403 quota errors).
|
|
4
18
|
* Matches Zero's gmail-rate-limit.ts schedule: up to 10 attempts, 60s base delay. */
|
|
5
19
|
export declare function withRetry<T>(fn: () => Promise<T>, maxAttempts?: number, delayMs?: number): Promise<T>;
|
|
20
|
+
declare const AuthError_base: errore.FactoryTaggedErrorClass<"AuthError", "Authentication failed for $email: $reason", Error>;
|
|
21
|
+
/** Returned by client methods when authentication fails (expired token, revoked access, etc.).
|
|
22
|
+
* Callers check with `instanceof AuthError` and TypeScript narrows the type. */
|
|
23
|
+
export declare class AuthError extends AuthError_base {
|
|
24
|
+
}
|
|
25
|
+
declare const NotFoundError_base: errore.FactoryTaggedErrorClass<"NotFoundError", "$resource not found", Error>;
|
|
26
|
+
/** Returned when a requested resource doesn't exist (calendar, event, thread, draft, label). */
|
|
27
|
+
export declare class NotFoundError extends NotFoundError_base {
|
|
28
|
+
}
|
|
29
|
+
declare const EmptyThreadError_base: errore.FactoryTaggedErrorClass<"EmptyThreadError", "No messages in thread $threadId", Error>;
|
|
30
|
+
/** Returned when a thread has no messages (empty thread). */
|
|
31
|
+
export declare class EmptyThreadError extends EmptyThreadError_base {
|
|
32
|
+
}
|
|
33
|
+
declare const ParseError_base: errore.FactoryTaggedErrorClass<"ParseError", "Failed to parse $what: $reason", Error>;
|
|
34
|
+
/** Returned when data cannot be parsed (iCal, event response, raw email). */
|
|
35
|
+
export declare class ParseError extends ParseError_base {
|
|
36
|
+
}
|
|
37
|
+
declare const MissingDataError_base: errore.FactoryTaggedErrorClass<"MissingDataError", "Missing $what for $resource", Error>;
|
|
38
|
+
/** Returned when required data is missing from an API response or cached object. */
|
|
39
|
+
export declare class MissingDataError extends MissingDataError_base {
|
|
40
|
+
}
|
|
41
|
+
declare const ValidationError_base: errore.FactoryTaggedErrorClass<"ValidationError", "Invalid $field: $reason", Error>;
|
|
42
|
+
/** Returned when user input fails validation (reminder format, time expressions, etc.). */
|
|
43
|
+
export declare class ValidationError extends ValidationError_base {
|
|
44
|
+
}
|
|
45
|
+
declare const ApiError_base: errore.FactoryTaggedErrorClass<"ApiError", "API call failed: $reason", Error>;
|
|
46
|
+
/** Returned when a non-auth, non-ratelimit API call fails. */
|
|
47
|
+
export declare class ApiError extends ApiError_base {
|
|
48
|
+
}
|
|
49
|
+
/** Detect auth-like errors from underlying libraries (tsdav string errors, googleapis structured errors).
|
|
50
|
+
* Used inside clients to decide whether to return an AuthError.
|
|
51
|
+
* NOTE: String matching here is intentional — this is the boundary layer that converts
|
|
52
|
+
* untyped external library exceptions into typed AuthError values (errore "wrapping libraries" pattern). */
|
|
53
|
+
export declare function isAuthLikeError(err: unknown): boolean;
|
|
6
54
|
export declare function isRateLimitError(err: any): boolean;
|
|
55
|
+
export {};
|
package/dist/api-utils.js
CHANGED
|
@@ -1,19 +1,42 @@
|
|
|
1
1
|
// Shared API utilities for Gmail and Calendar clients.
|
|
2
2
|
// Retry logic for rate limit errors and bounded concurrency helper.
|
|
3
3
|
// Extracted from gmail-client.ts to be reused across API clients.
|
|
4
|
+
//
|
|
5
|
+
// Auth error handling follows the errore pattern (errors as values):
|
|
6
|
+
// - Clients return AuthError instead of throwing for auth failures
|
|
7
|
+
// - Callers narrow with instanceof, no try/catch or string matching needed
|
|
8
|
+
// - See https://errore.org/ for the philosophy
|
|
9
|
+
import * as errore from 'errore';
|
|
4
10
|
const MAX_CONCURRENCY = 10;
|
|
5
|
-
/**
|
|
11
|
+
/** Generic truthy type guard for Array.filter() chains.
|
|
12
|
+
* Useful to drop null/undefined placeholders while preserving inferred item types. */
|
|
13
|
+
export function isTruthy(value) {
|
|
14
|
+
return Boolean(value);
|
|
15
|
+
}
|
|
16
|
+
/** Run promises with bounded concurrency.
|
|
17
|
+
* Error-aware: if any callback returns an Error instance, remaining work is
|
|
18
|
+
* aborted and that error is returned as a value (no throwing needed).
|
|
19
|
+
* Callbacks should return Error for fatal failures (auth) and null for skip.
|
|
20
|
+
* The success array is typed without Error — errors are only in the Error branch. */
|
|
6
21
|
export async function mapConcurrent(items, fn, concurrency = MAX_CONCURRENCY) {
|
|
7
22
|
const results = [];
|
|
8
23
|
let index = 0;
|
|
24
|
+
let fatalError = null;
|
|
9
25
|
async function worker() {
|
|
10
|
-
while (index < items.length) {
|
|
26
|
+
while (index < items.length && !fatalError) {
|
|
11
27
|
const i = index++;
|
|
12
|
-
|
|
28
|
+
const result = await fn(items[i]);
|
|
29
|
+
if (result instanceof Error) {
|
|
30
|
+
fatalError = result;
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
results[i] = result;
|
|
13
34
|
}
|
|
14
35
|
}
|
|
15
36
|
const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => worker());
|
|
16
37
|
await Promise.all(workers);
|
|
38
|
+
if (fatalError)
|
|
39
|
+
return fatalError;
|
|
17
40
|
return results;
|
|
18
41
|
}
|
|
19
42
|
/** Simple retry for rate limit errors (429 and 403 quota errors).
|
|
@@ -32,6 +55,69 @@ export async function withRetry(fn, maxAttempts = 10, delayMs = 60000) {
|
|
|
32
55
|
}
|
|
33
56
|
throw new Error('unreachable');
|
|
34
57
|
}
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
// Auth errors (errore pattern: errors as values, not exceptions)
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
/** Returned by client methods when authentication fails (expired token, revoked access, etc.).
|
|
62
|
+
* Callers check with `instanceof AuthError` and TypeScript narrows the type. */
|
|
63
|
+
export class AuthError extends errore.createTaggedError({
|
|
64
|
+
name: 'AuthError',
|
|
65
|
+
message: 'Authentication failed for $email: $reason',
|
|
66
|
+
}) {
|
|
67
|
+
}
|
|
68
|
+
/** Returned when a requested resource doesn't exist (calendar, event, thread, draft, label). */
|
|
69
|
+
export class NotFoundError extends errore.createTaggedError({
|
|
70
|
+
name: 'NotFoundError',
|
|
71
|
+
message: '$resource not found',
|
|
72
|
+
}) {
|
|
73
|
+
}
|
|
74
|
+
/** Returned when a thread has no messages (empty thread). */
|
|
75
|
+
export class EmptyThreadError extends errore.createTaggedError({
|
|
76
|
+
name: 'EmptyThreadError',
|
|
77
|
+
message: 'No messages in thread $threadId',
|
|
78
|
+
}) {
|
|
79
|
+
}
|
|
80
|
+
/** Returned when data cannot be parsed (iCal, event response, raw email). */
|
|
81
|
+
export class ParseError extends errore.createTaggedError({
|
|
82
|
+
name: 'ParseError',
|
|
83
|
+
message: 'Failed to parse $what: $reason',
|
|
84
|
+
}) {
|
|
85
|
+
}
|
|
86
|
+
/** Returned when required data is missing from an API response or cached object. */
|
|
87
|
+
export class MissingDataError extends errore.createTaggedError({
|
|
88
|
+
name: 'MissingDataError',
|
|
89
|
+
message: 'Missing $what for $resource',
|
|
90
|
+
}) {
|
|
91
|
+
}
|
|
92
|
+
/** Returned when user input fails validation (reminder format, time expressions, etc.). */
|
|
93
|
+
export class ValidationError extends errore.createTaggedError({
|
|
94
|
+
name: 'ValidationError',
|
|
95
|
+
message: 'Invalid $field: $reason',
|
|
96
|
+
}) {
|
|
97
|
+
}
|
|
98
|
+
/** Returned when a non-auth, non-ratelimit API call fails. */
|
|
99
|
+
export class ApiError extends errore.createTaggedError({
|
|
100
|
+
name: 'ApiError',
|
|
101
|
+
message: 'API call failed: $reason',
|
|
102
|
+
}) {
|
|
103
|
+
}
|
|
104
|
+
/** Detect auth-like errors from underlying libraries (tsdav string errors, googleapis structured errors).
|
|
105
|
+
* Used inside clients to decide whether to return an AuthError.
|
|
106
|
+
* NOTE: String matching here is intentional — this is the boundary layer that converts
|
|
107
|
+
* untyped external library exceptions into typed AuthError values (errore "wrapping libraries" pattern). */
|
|
108
|
+
export function isAuthLikeError(err) {
|
|
109
|
+
const e = err;
|
|
110
|
+
const status = e?.code ?? e?.status ?? e?.response?.status;
|
|
111
|
+
if (status === 401)
|
|
112
|
+
return true;
|
|
113
|
+
if (status === 403 && !isRateLimitError(e))
|
|
114
|
+
return true;
|
|
115
|
+
const msg = String(err);
|
|
116
|
+
return msg.includes('Invalid credentials') || msg.includes('Unauthorized') || msg.includes('invalid_grant');
|
|
117
|
+
}
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
// Rate limit detection
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
35
121
|
export function isRateLimitError(err) {
|
|
36
122
|
const status = err?.code ?? err?.status ?? err?.response?.status;
|
|
37
123
|
if (status === 429)
|
package/dist/api-utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-utils.js","sourceRoot":"","sources":["../src/api-utils.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,oEAAoE;AACpE,kEAAkE;
|
|
1
|
+
{"version":3,"file":"api-utils.js","sourceRoot":"","sources":["../src/api-utils.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.d.ts
CHANGED
|
@@ -1,23 +1,39 @@
|
|
|
1
1
|
import { OAuth2Client } from 'google-auth-library';
|
|
2
2
|
import { GmailClient } from './gmail-client.js';
|
|
3
3
|
import { CalendarClient } from './calendar-client.js';
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Create an OAuth2Client. If appId is provided, looks up the matching
|
|
6
|
+
* client credentials from OAUTH_CLIENTS by client ID. Falls back to
|
|
7
|
+
* the active client / env vars.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createOAuth2Client(appId?: string): OAuth2Client;
|
|
10
|
+
export interface AccountId {
|
|
11
|
+
email: string;
|
|
12
|
+
appId: string;
|
|
13
|
+
}
|
|
14
|
+
interface BrowserAuthOptions {
|
|
15
|
+
openBrowser?: boolean;
|
|
16
|
+
allowManualCodeEntry?: boolean;
|
|
17
|
+
showInstructions?: boolean;
|
|
18
|
+
}
|
|
5
19
|
/**
|
|
6
20
|
* Run the full browser OAuth flow and save the account to the DB.
|
|
7
|
-
* Returns
|
|
21
|
+
* Returns either a successful login payload or an Error value.
|
|
8
22
|
*/
|
|
9
|
-
export declare function login(): Promise<{
|
|
23
|
+
export declare function login(appId?: string, options?: BrowserAuthOptions): Promise<{
|
|
10
24
|
email: string;
|
|
25
|
+
appId: string;
|
|
11
26
|
client: GmailClient;
|
|
12
|
-
}>;
|
|
13
|
-
export declare function logout(email: string): Promise<void>;
|
|
14
|
-
export declare function listAccounts(): Promise<
|
|
27
|
+
} | Error>;
|
|
28
|
+
export declare function logout(email: string): Promise<void | Error>;
|
|
29
|
+
export declare function listAccounts(): Promise<AccountId[]>;
|
|
15
30
|
/**
|
|
16
31
|
* Get authenticated GmailClient instances for all accounts (or filtered by email list).
|
|
17
32
|
* If no accounts are registered, throws with a helpful message.
|
|
18
33
|
*/
|
|
19
34
|
export declare function getClients(accounts?: string[]): Promise<Array<{
|
|
20
35
|
email: string;
|
|
36
|
+
appId: string;
|
|
21
37
|
client: GmailClient;
|
|
22
38
|
}>>;
|
|
23
39
|
/**
|
|
@@ -26,6 +42,7 @@ export declare function getClients(accounts?: string[]): Promise<Array<{
|
|
|
26
42
|
*/
|
|
27
43
|
export declare function getClient(accounts?: string[]): Promise<{
|
|
28
44
|
email: string;
|
|
45
|
+
appId: string;
|
|
29
46
|
client: GmailClient;
|
|
30
47
|
}>;
|
|
31
48
|
/**
|
|
@@ -33,6 +50,7 @@ export declare function getClient(accounts?: string[]): Promise<{
|
|
|
33
50
|
*/
|
|
34
51
|
export declare function getCalendarClients(accounts?: string[]): Promise<Array<{
|
|
35
52
|
email: string;
|
|
53
|
+
appId: string;
|
|
36
54
|
client: CalendarClient;
|
|
37
55
|
}>>;
|
|
38
56
|
/**
|
|
@@ -41,10 +59,13 @@ export declare function getCalendarClients(accounts?: string[]): Promise<Array<{
|
|
|
41
59
|
*/
|
|
42
60
|
export declare function getCalendarClient(accounts?: string[]): Promise<{
|
|
43
61
|
email: string;
|
|
62
|
+
appId: string;
|
|
44
63
|
client: CalendarClient;
|
|
45
64
|
}>;
|
|
46
65
|
export interface AuthStatus {
|
|
47
66
|
email: string;
|
|
67
|
+
appId: string;
|
|
48
68
|
expiresAt?: Date;
|
|
49
69
|
}
|
|
50
70
|
export declare function getAuthStatuses(): Promise<AuthStatus[]>;
|
|
71
|
+
export {};
|