@marcfargas/go-easy 0.0.1 → 0.3.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 (113) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/LICENSE +21 -0
  3. package/README.md +224 -0
  4. package/dist/auth-flow.d.ts +50 -0
  5. package/dist/auth-flow.d.ts.map +1 -0
  6. package/dist/auth-flow.js +219 -0
  7. package/dist/auth-flow.js.map +1 -0
  8. package/dist/auth-server.d.ts +18 -0
  9. package/dist/auth-server.d.ts.map +1 -0
  10. package/dist/auth-server.js +327 -0
  11. package/dist/auth-server.js.map +1 -0
  12. package/dist/auth-store.d.ts +81 -0
  13. package/dist/auth-store.d.ts.map +1 -0
  14. package/dist/auth-store.js +185 -0
  15. package/dist/auth-store.js.map +1 -0
  16. package/dist/auth.d.ts +47 -0
  17. package/dist/auth.d.ts.map +1 -0
  18. package/dist/auth.js +131 -0
  19. package/dist/auth.js.map +1 -0
  20. package/dist/bin/calendar.d.ts +17 -0
  21. package/dist/bin/calendar.d.ts.map +1 -0
  22. package/dist/bin/calendar.js +224 -0
  23. package/dist/bin/calendar.js.map +1 -0
  24. package/dist/bin/drive.d.ts +18 -0
  25. package/dist/bin/drive.d.ts.map +1 -0
  26. package/dist/bin/drive.js +205 -0
  27. package/dist/bin/drive.js.map +1 -0
  28. package/dist/bin/easy.d.ts +11 -0
  29. package/dist/bin/easy.d.ts.map +1 -0
  30. package/dist/bin/easy.js +140 -0
  31. package/dist/bin/easy.js.map +1 -0
  32. package/dist/bin/gmail.d.ts +25 -0
  33. package/dist/bin/gmail.d.ts.map +1 -0
  34. package/dist/bin/gmail.js +243 -0
  35. package/dist/bin/gmail.js.map +1 -0
  36. package/dist/bin/tasks.d.ts +17 -0
  37. package/dist/bin/tasks.d.ts.map +1 -0
  38. package/dist/bin/tasks.js +190 -0
  39. package/dist/bin/tasks.js.map +1 -0
  40. package/dist/calendar/helpers.d.ts +35 -0
  41. package/dist/calendar/helpers.d.ts.map +1 -0
  42. package/dist/calendar/helpers.js +178 -0
  43. package/dist/calendar/helpers.js.map +1 -0
  44. package/dist/calendar/index.d.ts +64 -0
  45. package/dist/calendar/index.d.ts.map +1 -0
  46. package/dist/calendar/index.js +210 -0
  47. package/dist/calendar/index.js.map +1 -0
  48. package/dist/calendar/types.d.ts +191 -0
  49. package/dist/calendar/types.d.ts.map +1 -0
  50. package/dist/calendar/types.js +12 -0
  51. package/dist/calendar/types.js.map +1 -0
  52. package/dist/drive/helpers.d.ts +22 -0
  53. package/dist/drive/helpers.d.ts.map +1 -0
  54. package/dist/drive/helpers.js +85 -0
  55. package/dist/drive/helpers.js.map +1 -0
  56. package/dist/drive/index.d.ts +114 -0
  57. package/dist/drive/index.d.ts.map +1 -0
  58. package/dist/drive/index.js +418 -0
  59. package/dist/drive/index.js.map +1 -0
  60. package/dist/drive/types.d.ts +91 -0
  61. package/dist/drive/types.d.ts.map +1 -0
  62. package/dist/drive/types.js +5 -0
  63. package/dist/drive/types.js.map +1 -0
  64. package/dist/errors.d.ts +58 -0
  65. package/dist/errors.d.ts.map +1 -0
  66. package/dist/errors.js +73 -0
  67. package/dist/errors.js.map +1 -0
  68. package/dist/gmail/helpers.d.ts +59 -0
  69. package/dist/gmail/helpers.d.ts.map +1 -0
  70. package/dist/gmail/helpers.js +308 -0
  71. package/dist/gmail/helpers.js.map +1 -0
  72. package/dist/gmail/index.d.ts +95 -0
  73. package/dist/gmail/index.d.ts.map +1 -0
  74. package/dist/gmail/index.js +465 -0
  75. package/dist/gmail/index.js.map +1 -0
  76. package/dist/gmail/markdown.d.ts +22 -0
  77. package/dist/gmail/markdown.d.ts.map +1 -0
  78. package/dist/gmail/markdown.js +30 -0
  79. package/dist/gmail/markdown.js.map +1 -0
  80. package/dist/gmail/types.d.ts +154 -0
  81. package/dist/gmail/types.d.ts.map +1 -0
  82. package/dist/gmail/types.js +5 -0
  83. package/dist/gmail/types.js.map +1 -0
  84. package/dist/index.d.ts +27 -0
  85. package/dist/index.d.ts.map +1 -0
  86. package/dist/index.js +29 -0
  87. package/dist/index.js.map +1 -0
  88. package/dist/safety.d.ts +58 -0
  89. package/dist/safety.d.ts.map +1 -0
  90. package/dist/safety.js +61 -0
  91. package/dist/safety.js.map +1 -0
  92. package/dist/scopes.d.ts +16 -0
  93. package/dist/scopes.d.ts.map +1 -0
  94. package/dist/scopes.js +28 -0
  95. package/dist/scopes.js.map +1 -0
  96. package/dist/tasks/helpers.d.ts +10 -0
  97. package/dist/tasks/helpers.d.ts.map +1 -0
  98. package/dist/tasks/helpers.js +33 -0
  99. package/dist/tasks/helpers.js.map +1 -0
  100. package/dist/tasks/index.d.ts +63 -0
  101. package/dist/tasks/index.d.ts.map +1 -0
  102. package/dist/tasks/index.js +253 -0
  103. package/dist/tasks/index.js.map +1 -0
  104. package/dist/tasks/types.d.ts +79 -0
  105. package/dist/tasks/types.d.ts.map +1 -0
  106. package/dist/tasks/types.js +5 -0
  107. package/dist/tasks/types.js.map +1 -0
  108. package/package.json +73 -4
  109. package/skills/go-easy/SKILL.md +146 -0
  110. package/skills/go-easy/calendar.md +366 -0
  111. package/skills/go-easy/drive.md +309 -0
  112. package/skills/go-easy/gmail.md +478 -0
  113. package/skills/go-easy/tasks.md +260 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,90 @@
1
+ # @marcfargas/go-easy
2
+
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`8cf8524`](https://github.com/marcfargas/go-easy/commit/8cf85243659e1151b896a69f5405534062a82899) Thanks [@marcfargas](https://github.com/marcfargas)! - Beta release — own auth system, Google Tasks, reply CLI, file-based body flags, Markdown emails.
8
+
9
+ ### Auth (BREAKING)
10
+
11
+ go-easy now owns its own OAuth2 tokens at `~/.go-easy/` instead of reading from legacy CLI stores (`~/.gmcli`, `~/.gdcli`, `~/.gccli`).
12
+
13
+ - `npx go-easy auth add <email>` — agent-compatible two-phase OAuth flow (start → poll)
14
+ - `npx go-easy auth list` — list configured accounts and scopes
15
+ - `npx go-easy auth remove <email> --confirm` — remove an account
16
+ - One combined token per account covers Gmail + Drive + Calendar + Tasks
17
+ - Specific error codes with `fix` field: `AUTH_NO_ACCOUNT`, `AUTH_MISSING_SCOPE`, `AUTH_TOKEN_REVOKED`, `AUTH_NO_CREDENTIALS`
18
+
19
+ ### Google Tasks (NEW)
20
+
21
+ New service module and CLI for Google Tasks API:
22
+
23
+ - `npx go-tasks <account> lists` — list task lists
24
+ - `npx go-tasks <account> tasks <listId>` — list tasks with pagination
25
+ - `npx go-tasks <account> get/add/update/complete/move/delete` — full CRUD
26
+ - `npx go-tasks <account> create-list/delete-list/clear` — list management
27
+ - Subtask support via `--parent` flag
28
+ - Library: `@marcfargas/go-easy/tasks` export
29
+ - Requires re-auth for existing accounts (`npx go-easy auth add <email>`)
30
+
31
+ ### Gmail CLI
32
+
33
+ - Add `reply` command — reply and reply-all with `--reply-all` flag (DESTRUCTIVE, requires `--confirm`)
34
+ - Add `--in-reply-to` flag for `draft` command (thread association)
35
+ - Add `--cc` and `--bcc` flags for `draft` and `send` commands
36
+ - Add `--page-token` for `search` and `drafts` pagination
37
+
38
+ ### Body Flags (BREAKING)
39
+
40
+ Replace inline `--body`, `--html`, `--md` flags with file-based alternatives:
41
+
42
+ - `--body-text-file=<path>` — read plain text body from UTF-8 file
43
+ - `--body-html-file=<path>` — read HTML body from UTF-8 file
44
+ - `--body-md-file=<path>` — read Markdown body from file (auto-converted to HTML)
45
+
46
+ This eliminates shell escaping, encoding, and multiline issues for agent use.
47
+
48
+ ### Markdown Email Support
49
+
50
+ - New `markdown` option on `send`, `reply`, `forward`, and `createDraft`
51
+ - Auto-converts Markdown to email-safe HTML with inline styles
52
+ - GFM support: tables, strikethrough, code blocks, links, lists
53
+ - `markdownToHtml()` helper exported from `@marcfargas/go-easy/gmail`
54
+
55
+ ### Forward Improvements
56
+
57
+ - Forward creates a draft by default (WRITE, no safety gate)
58
+ - `--send-now --confirm` to send immediately (DESTRUCTIVE)
59
+ - Attachment filtering: `--include=name` and `--exclude=name` (substring match)
60
+ - `--no-thread` to break out of the original thread
61
+ - Body content appears above the forwarded message
62
+
63
+ ### Calendar
64
+
65
+ - Support all event types: working location, out-of-office, focus time, birthday
66
+ - `--page-token` for events pagination
67
+ - Fix `update` command: use PATCH instead of PUT to prevent data loss on partial updates
68
+
69
+ ### Drive
70
+
71
+ - `--page-token` for `ls` and `search` pagination
72
+
73
+ ### Fixes
74
+
75
+ - RFC 2047 encode Subject headers with non-ASCII characters
76
+ - Fix forward threading (keep in original thread by default)
77
+ - Fix auth HTML pages: add `<meta charset="utf-8">` for emoji rendering
78
+
79
+ ## 0.2.0
80
+
81
+ ### Minor Changes
82
+
83
+ - [`5f424e1`](https://github.com/marcfargas/go-easy/commit/5f424e16c3c9971c2be196725a5d9c1d7e88633b) Thanks [@marcfargas](https://github.com/marcfargas)! - Initial release — Gmail, Drive & Calendar APIs for AI agents and humans.
84
+
85
+ - Gmail: search, getMessage, getThread, send, reply, forward, createDraft, sendDraft, listDrafts, listLabels, batchModifyLabels, getAttachmentContent, getProfile
86
+ - Drive: listFiles, searchFiles, getFile, downloadFile, exportFile, uploadFile, createFolder, moveFile, renameFile, copyFile, trashFile, listPermissions, shareFile, unshareFile
87
+ - Calendar: listCalendars, listEvents, getEvent, createEvent, updateEvent, deleteEvent, queryFreeBusy
88
+ - Gateway CLIs: go-gmail, go-drive, go-calendar (JSON output, --confirm safety)
89
+ - Safety model: READ/WRITE/DESTRUCTIVE operation classification
90
+ - Auth: multi-account OAuth2 with per-service token stores
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Marc Fargas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,224 @@
1
+ # go-easy 🟢
2
+
3
+ > Google APIs made easy — Gmail, Drive & Calendar. For AI agents and humans.
4
+
5
+ Thin TypeScript wrappers over Google's individual `@googleapis/*` packages with:
6
+ - **Own auth** — unified OAuth2 with combined tokens, agent-compatible two-phase flow
7
+ - **Agent-friendly types** — structured `GmailMessage`, `DriveFile`, `CalendarEvent`
8
+ - **Safety guards** — destructive operations (send, share, delete) require explicit confirmation
9
+ - **JSON gateways** — CLI tools that always output structured JSON
10
+ - **File-based body** — email bodies read from files, not CLI args (no shell escaping issues)
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ # As a library
16
+ npm install @marcfargas/go-easy
17
+
18
+ # As CLI tools (no install needed)
19
+ npx go-gmail you@example.com search "is:unread"
20
+ npx go-drive you@example.com ls
21
+ npx go-calendar you@example.com events primary
22
+ ```
23
+
24
+ Requires **Node.js ≥ 20**.
25
+
26
+ ## Auth Setup
27
+
28
+ go-easy manages its own OAuth2 tokens in `~/.go-easy/`.
29
+
30
+ ### Prerequisites
31
+
32
+ 1. Create a project in [Google Cloud Console](https://console.cloud.google.com/)
33
+ 2. Enable the Gmail, Drive, and Calendar APIs
34
+ 3. Create OAuth2 credentials (Desktop application type)
35
+ 4. Save credentials to `~/.go-easy/credentials.json`:
36
+
37
+ ```json
38
+ {
39
+ "clientId": "YOUR_CLIENT_ID.apps.googleusercontent.com",
40
+ "clientSecret": "YOUR_CLIENT_SECRET"
41
+ }
42
+ ```
43
+
44
+ ### Add an account
45
+
46
+ ```bash
47
+ npx go-easy auth add you@example.com
48
+ # → { "status": "started", "authUrl": "https://accounts.google.com/..." }
49
+ # Open the URL, authorize, then poll:
50
+ npx go-easy auth add you@example.com
51
+ # → { "status": "complete", "email": "you@example.com", "scopes": ["gmail", "drive", "calendar"] }
52
+ ```
53
+
54
+ One combined token covers Gmail + Drive + Calendar. The flow is agent-compatible — two separate CLI calls (start + poll), no streaming stdout needed.
55
+
56
+ ### Manage accounts
57
+
58
+ ```bash
59
+ npx go-easy auth list # List configured accounts
60
+ npx go-easy auth add you@example.com # Add or upgrade account
61
+ npx go-easy auth remove you@example.com --confirm # Remove account
62
+ ```
63
+
64
+ ## Quick Start
65
+
66
+ ```ts
67
+ import { getAuth } from '@marcfargas/go-easy/auth';
68
+ import { search, send } from '@marcfargas/go-easy/gmail';
69
+ import { setSafetyContext } from '@marcfargas/go-easy';
70
+
71
+ const auth = await getAuth('gmail', 'you@example.com');
72
+
73
+ // Search (READ — no safety gate)
74
+ const results = await search(auth, { query: 'is:unread from:client' });
75
+ console.log(results.items);
76
+
77
+ // Send (DESTRUCTIVE — requires safety context)
78
+ setSafetyContext({
79
+ confirm: async (op) => {
80
+ console.log(`⚠️ ${op.description}`);
81
+ return true; // or prompt the user
82
+ },
83
+ });
84
+
85
+ await send(auth, {
86
+ to: 'client@example.com',
87
+ subject: 'Invoice attached',
88
+ markdown: '# Invoice\n\nPlease find attached.',
89
+ attachments: ['./invoice.pdf'],
90
+ });
91
+ ```
92
+
93
+ ## Gateway CLIs
94
+
95
+ All gateway CLIs output JSON to stdout and work via `npx`:
96
+
97
+ ```bash
98
+ # Gmail
99
+ npx go-gmail you@example.com search "is:unread" --max=10
100
+ npx go-gmail you@example.com get <messageId>
101
+ npx go-gmail you@example.com reply <messageId> --body-text-file=reply.txt --confirm
102
+ npx go-gmail you@example.com send --to=x@y.com --subject="Hi" --body-text-file=body.txt --confirm
103
+
104
+ # Drive
105
+ npx go-drive you@example.com ls
106
+ npx go-drive you@example.com search "quarterly report"
107
+ npx go-drive you@example.com upload ./file.pdf --folder=<folderId>
108
+
109
+ # Calendar
110
+ npx go-calendar you@example.com events primary --from=2026-02-01T00:00:00Z
111
+ npx go-calendar you@example.com create primary --summary="Meeting" --start=... --end=...
112
+ npx go-calendar you@example.com freebusy primary --from=... --to=...
113
+ ```
114
+
115
+ Body content is always read from files (`--body-text-file`, `--body-html-file`, `--body-md-file`), never passed inline.
116
+
117
+ Destructive operations require `--confirm`. Without it, they show what *would* happen and exit with code 2.
118
+
119
+ ## Services
120
+
121
+ | Service | Module | Gateway | Status |
122
+ |---------|--------|---------|--------|
123
+ | Gmail | `@marcfargas/go-easy/gmail` | `npx go-gmail` | ✅ Ready |
124
+ | Drive | `@marcfargas/go-easy/drive` | `npx go-drive` | ✅ Ready |
125
+ | Calendar | `@marcfargas/go-easy/calendar` | `npx go-calendar` | ✅ Ready |
126
+
127
+ ### Gmail
128
+
129
+ | Function | Safety | Description |
130
+ |---|---|---|
131
+ | `search` | READ | Search messages by Gmail query |
132
+ | `getMessage` | READ | Get a single message with parsed fields |
133
+ | `getThread` | READ | Get a full conversation thread |
134
+ | `listLabels` | READ | List all labels |
135
+ | `getAttachmentContent` | READ | Download an attachment as Buffer |
136
+ | `getProfile` | READ | Get the authenticated email address |
137
+ | `createDraft` | WRITE | Create a draft (no send) |
138
+ | `listDrafts` | READ | List existing drafts |
139
+ | `batchModifyLabels` | WRITE | Add/remove labels on multiple messages |
140
+ | `markdownToHtml` | — | Convert Markdown to email-safe HTML |
141
+ | `send` | ⚠️ DESTRUCTIVE | Send a new email (supports `markdown` option) |
142
+ | `reply` | ⚠️ DESTRUCTIVE | Reply / reply-all to a message |
143
+ | `forward` | WRITE / ⚠️ DESTRUCTIVE | Forward as draft (default) or send (`sendNow`). Attachment filtering. |
144
+ | `sendDraft` | ⚠️ DESTRUCTIVE | Send an existing draft |
145
+
146
+ ### Drive
147
+
148
+ | Function | Safety | Description |
149
+ |---|---|---|
150
+ | `listFiles` | READ | List folder contents or query by metadata |
151
+ | `searchFiles` | READ | Full-text search inside file contents |
152
+ | `getFile` | READ | Get file metadata by ID |
153
+ | `downloadFile` | READ | Download binary files as Buffer |
154
+ | `exportFile` | READ | Export Workspace files (Docs → pdf/docx, Sheets → xlsx/csv, etc.) |
155
+ | `listPermissions` | READ | List sharing permissions on a file |
156
+ | `uploadFile` | WRITE | Upload a local file |
157
+ | `createFolder` | WRITE | Create a folder |
158
+ | `moveFile` | WRITE | Move a file to a different folder |
159
+ | `renameFile` | WRITE | Rename a file |
160
+ | `copyFile` | WRITE | Copy a file |
161
+ | `trashFile` | ⚠️ DESTRUCTIVE | Trash a file |
162
+ | `shareFile` | ⚠️ DESTRUCTIVE* | Share a file (*public sharing only; user/group is WRITE) |
163
+ | `unshareFile` | ⚠️ DESTRUCTIVE | Remove a sharing permission |
164
+
165
+ ### Calendar
166
+
167
+ | Function | Safety | Description |
168
+ |---|---|---|
169
+ | `listCalendars` | READ | List all calendars for the account |
170
+ | `listEvents` | READ | List events with time range, search, pagination |
171
+ | `getEvent` | READ | Get a single event by ID |
172
+ | `queryFreeBusy` | READ | Check availability across calendars |
173
+ | `createEvent` | WRITE | Create an event (with attendees, all-day, location, OOO, focus time) |
174
+ | `updateEvent` | WRITE | Update an existing event (full replace) |
175
+ | `deleteEvent` | ⚠️ DESTRUCTIVE | Delete an event (warns about attendee cancellation) |
176
+
177
+ ## Safety Model
178
+
179
+ Operations are classified into three levels:
180
+
181
+ | Level | Gate | Examples |
182
+ |-------|------|----------|
183
+ | **READ** | None | search, getMessage, listLabels |
184
+ | **WRITE** | Logged | createDraft, batchModifyLabels, upload |
185
+ | **DESTRUCTIVE** | Blocked unless confirmed | send, reply, forward, share, delete |
186
+
187
+ Set up a `SafetyContext` at startup to handle confirmation prompts.
188
+ Without one, all destructive operations are blocked by default.
189
+
190
+ ## Module Structure
191
+
192
+ go-easy uses **subpath exports** — import only what you need:
193
+
194
+ ```ts
195
+ import { getAuth } from '@marcfargas/go-easy/auth';
196
+ import { search, send } from '@marcfargas/go-easy/gmail';
197
+ import { listFiles, uploadFile } from '@marcfargas/go-easy/drive';
198
+ import { listEvents, createEvent } from '@marcfargas/go-easy/calendar';
199
+ import { setSafetyContext } from '@marcfargas/go-easy';
200
+ ```
201
+
202
+ | Import path | What's in it |
203
+ |---|---|
204
+ | `@marcfargas/go-easy` | Safety context, errors, plus `gmail`/`drive`/`calendar` as namespaces |
205
+ | `@marcfargas/go-easy/auth` | `getAuth`, `listAccounts`, `listAllAccounts`, `clearAuthCache` |
206
+ | `@marcfargas/go-easy/auth-store` | `readAccountStore`, `writeAccountStore`, `findAccount`, etc. |
207
+ | `@marcfargas/go-easy/scopes` | `SCOPES`, `ALL_SCOPES`, `scopeToService` |
208
+ | `@marcfargas/go-easy/gmail` | All Gmail operations |
209
+ | `@marcfargas/go-easy/drive` | All Drive operations |
210
+ | `@marcfargas/go-easy/calendar` | All Calendar operations |
211
+
212
+ ## Development
213
+
214
+ ```bash
215
+ npm install # install deps
216
+ npm run build # compile TypeScript
217
+ npm test # run tests (vitest)
218
+ npm run lint # type-check without emitting
219
+ npm run dev # watch mode
220
+ ```
221
+
222
+ ## License
223
+
224
+ MIT
@@ -0,0 +1,50 @@
1
+ /**
2
+ * auth-flow — Two-phase OAuth flow for agent-compatible auth.
3
+ *
4
+ * Phase 1 (start): Spawn background auth server, return URL.
5
+ * Phase 2 (poll): Check pending file for completion status.
6
+ *
7
+ * The agent calls `npx go-easy auth add <email>` which:
8
+ * - On first call: starts the server, returns { status: "started", authUrl }
9
+ * - On subsequent calls: polls and returns current status
10
+ * - When user completes auth: returns { status: "complete" }
11
+ */
12
+ export type AuthFlowStatus = {
13
+ status: 'started';
14
+ authUrl: string;
15
+ expiresIn: number;
16
+ } | {
17
+ status: 'waiting';
18
+ authUrl: string;
19
+ expiresIn: number;
20
+ } | {
21
+ status: 'complete';
22
+ email: string;
23
+ scopes: string[];
24
+ } | {
25
+ status: 'partial';
26
+ email: string;
27
+ grantedScopes: string[];
28
+ missingScopes: string[];
29
+ message: string;
30
+ } | {
31
+ status: 'denied';
32
+ message: string;
33
+ } | {
34
+ status: 'expired';
35
+ message: string;
36
+ } | {
37
+ status: 'error';
38
+ message: string;
39
+ };
40
+ /**
41
+ * Start or poll the auth flow for an email.
42
+ *
43
+ * This is the single entry point — handles all states:
44
+ * - No session → start new auth server
45
+ * - Pending session with live server → return waiting/started
46
+ * - Completed session → return result, clean up
47
+ * - Stale session (dead pid) → clean up, restart
48
+ */
49
+ export declare function authAdd(email: string): Promise<AuthFlowStatus>;
50
+ //# sourceMappingURL=auth-flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-flow.d.ts","sourceRoot":"","sources":["../src/auth-flow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiBH,MAAM,MAAM,cAAc,GACtB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,GACvD;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACvG;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAmBzC;;;;;;;;GAQG;AACH,wBAAsB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAyGpE"}
@@ -0,0 +1,219 @@
1
+ /**
2
+ * auth-flow — Two-phase OAuth flow for agent-compatible auth.
3
+ *
4
+ * Phase 1 (start): Spawn background auth server, return URL.
5
+ * Phase 2 (poll): Check pending file for completion status.
6
+ *
7
+ * The agent calls `npx go-easy auth add <email>` which:
8
+ * - On first call: starts the server, returns { status: "started", authUrl }
9
+ * - On subsequent calls: polls and returns current status
10
+ * - When user completes auth: returns { status: "complete" }
11
+ */
12
+ import { readFile, unlink, stat } from 'node:fs/promises';
13
+ import { join } from 'node:path';
14
+ import { spawn } from 'node:child_process';
15
+ import { fileURLToPath } from 'node:url';
16
+ import { getPendingDir, readAccountStore, readCredentials, findAccount, } from './auth-store.js';
17
+ import { ALL_SCOPES, scopeToService } from './scopes.js';
18
+ import { AuthError } from './errors.js';
19
+ // ─── Public API ────────────────────────────────────────────
20
+ /**
21
+ * Start or poll the auth flow for an email.
22
+ *
23
+ * This is the single entry point — handles all states:
24
+ * - No session → start new auth server
25
+ * - Pending session with live server → return waiting/started
26
+ * - Completed session → return result, clean up
27
+ * - Stale session (dead pid) → clean up, restart
28
+ */
29
+ export async function authAdd(email) {
30
+ // Check if already fully configured
31
+ const store = await readAccountStore();
32
+ if (store) {
33
+ const account = findAccount(store, email);
34
+ if (account?.tokens.combined) {
35
+ const hasAll = ALL_SCOPES.every((s) => account.tokens.combined.scopes.includes(s));
36
+ if (hasAll) {
37
+ // Clean up any stale pending file
38
+ await cleanupPending(email);
39
+ return {
40
+ status: 'complete',
41
+ email: account.email,
42
+ scopes: account.tokens.combined.scopes.map((s) => scopeToService(s) ?? s),
43
+ };
44
+ }
45
+ }
46
+ }
47
+ // Check credentials exist
48
+ const creds = await readCredentials();
49
+ if (!creds) {
50
+ throw new AuthError('AUTH_NO_CREDENTIALS', {
51
+ message: 'OAuth client credentials not found at ~/.go-easy/credentials.json',
52
+ });
53
+ }
54
+ // Check for pending session
55
+ const pending = await readPending(email);
56
+ if (pending) {
57
+ // Terminal states: return and clean up
58
+ if (pending.status === 'complete') {
59
+ await cleanupPending(email);
60
+ return {
61
+ status: 'complete',
62
+ email: pending.email ?? email,
63
+ scopes: pending.scopes ?? [],
64
+ };
65
+ }
66
+ if (pending.status === 'partial') {
67
+ await cleanupPending(email);
68
+ return {
69
+ status: 'partial',
70
+ email: pending.email ?? email,
71
+ grantedScopes: pending.grantedScopes ?? [],
72
+ missingScopes: pending.missingScopes ?? [],
73
+ message: pending.message ?? 'Partial authorization',
74
+ };
75
+ }
76
+ if (pending.status === 'denied') {
77
+ await cleanupPending(email);
78
+ return {
79
+ status: 'denied',
80
+ message: pending.message ?? 'User declined authorization',
81
+ };
82
+ }
83
+ if (pending.status === 'expired') {
84
+ await cleanupPending(email);
85
+ return {
86
+ status: 'expired',
87
+ message: pending.message ?? 'Authorization timed out',
88
+ };
89
+ }
90
+ if (pending.status === 'error') {
91
+ await cleanupPending(email);
92
+ return {
93
+ status: 'error',
94
+ message: pending.message ?? 'Unknown error during authorization',
95
+ };
96
+ }
97
+ // Active session (waiting/started)
98
+ if (pending.status === 'waiting' || pending.status === 'started') {
99
+ // Check if the server process is still alive
100
+ if (pending.pid && isProcessAlive(pending.pid)) {
101
+ // Check if expired by time
102
+ if (pending.expiresAt && new Date(pending.expiresAt) < new Date()) {
103
+ await cleanupPending(email);
104
+ return {
105
+ status: 'expired',
106
+ message: 'Authorization timed out',
107
+ };
108
+ }
109
+ // Still waiting — return current state
110
+ const expiresIn = pending.expiresAt
111
+ ? Math.max(0, Math.floor((new Date(pending.expiresAt).getTime() - Date.now()) / 1000))
112
+ : 300;
113
+ return {
114
+ status: 'waiting',
115
+ authUrl: pending.authUrl ?? '',
116
+ expiresIn,
117
+ };
118
+ }
119
+ // PID is dead — stale session, clean up and restart
120
+ await cleanupPending(email);
121
+ }
122
+ }
123
+ // Start new auth flow
124
+ return startAuthServer(email);
125
+ }
126
+ // ─── Internal ──────────────────────────────────────────────
127
+ function pendingFilePath(email) {
128
+ return join(getPendingDir(), `${email.toLowerCase().trim()}.json`);
129
+ }
130
+ async function readPending(email) {
131
+ try {
132
+ const raw = await readFile(pendingFilePath(email), 'utf-8');
133
+ return JSON.parse(raw);
134
+ }
135
+ catch {
136
+ return null;
137
+ }
138
+ }
139
+ async function cleanupPending(email) {
140
+ try {
141
+ await unlink(pendingFilePath(email));
142
+ }
143
+ catch {
144
+ // Already deleted or never existed
145
+ }
146
+ }
147
+ function isProcessAlive(pid) {
148
+ try {
149
+ process.kill(pid, 0); // Signal 0 = just check existence
150
+ return true;
151
+ }
152
+ catch {
153
+ return false;
154
+ }
155
+ }
156
+ /**
157
+ * Spawn the auth-server as a fully detached background process.
158
+ *
159
+ * Uses stdio: 'ignore' so the child has no pipe ties to the parent.
160
+ * The child writes its startup info to the pending/<email>.json file.
161
+ * We poll that file briefly to get the authUrl.
162
+ */
163
+ async function startAuthServer(email) {
164
+ // Resolve the auth-server script path
165
+ const thisDir = typeof __dirname !== 'undefined'
166
+ ? __dirname
167
+ : fileURLToPath(new URL('.', import.meta.url));
168
+ const serverScript = join(thisDir, 'auth-server.js');
169
+ // Verify the script exists
170
+ try {
171
+ await stat(serverScript);
172
+ }
173
+ catch {
174
+ throw new AuthError('AUTH_ERROR', {
175
+ message: `Auth server script not found: ${serverScript}`,
176
+ });
177
+ }
178
+ // Clean up any old pending file first
179
+ await cleanupPending(email);
180
+ // Spawn fully detached — no pipes, child survives parent exit
181
+ const child = spawn(process.execPath, // node.exe
182
+ [serverScript, email.toLowerCase().trim(), '0'], {
183
+ detached: true,
184
+ stdio: 'ignore',
185
+ windowsHide: true,
186
+ });
187
+ child.unref();
188
+ // Poll the pending file for the server's startup info
189
+ const maxWait = 10_000; // 10s
190
+ const pollInterval = 100; // 100ms
191
+ const start = Date.now();
192
+ while (Date.now() - start < maxWait) {
193
+ await sleep(pollInterval);
194
+ const pending = await readPending(email);
195
+ if (pending && pending.authUrl) {
196
+ return {
197
+ status: 'started',
198
+ authUrl: pending.authUrl,
199
+ expiresIn: pending.expiresAt
200
+ ? Math.max(0, Math.floor((new Date(pending.expiresAt).getTime() - Date.now()) / 1000))
201
+ : 300,
202
+ };
203
+ }
204
+ // If the server wrote an error/terminal state, return it
205
+ if (pending && pending.status === 'error') {
206
+ return {
207
+ status: 'error',
208
+ message: pending.message ?? 'Auth server failed to start',
209
+ };
210
+ }
211
+ }
212
+ throw new AuthError('AUTH_ERROR', {
213
+ message: 'Auth server did not start within 10 seconds',
214
+ });
215
+ }
216
+ function sleep(ms) {
217
+ return new Promise((resolve) => setTimeout(resolve, ms));
218
+ }
219
+ //# sourceMappingURL=auth-flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-flow.js","sourceRoot":"","sources":["../src/auth-flow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * auth-server — Background loopback OAuth callback server.
4
+ *
5
+ * Spawned as a detached child by auth-flow.ts.
6
+ * Listens on 127.0.0.1:<port>, waits for Google OAuth callback,
7
+ * exchanges code for token, writes result to pending/<email>.json,
8
+ * updates accounts.json.
9
+ *
10
+ * Communicates with parent via:
11
+ * 1. stdout: JSON line with { port, pid, authUrl } (parent reads this, then detaches)
12
+ * 2. pending/<email>.json file (poll target for subsequent CLI calls)
13
+ *
14
+ * Usage (not meant to be called directly):
15
+ * node auth-server.js <email> <port>
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=auth-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-server.d.ts","sourceRoot":"","sources":["../src/auth-server.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG"}