gogcli-mcp 3.0.0 → 4.0.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 (50) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/dist/index.js +273 -748
  4. package/dist/lib.js +375 -785
  5. package/manifest.json +2 -2
  6. package/mint.yaml +37 -33
  7. package/package.json +3 -3
  8. package/server.json +2 -2
  9. package/src/attachments.ts +28 -34
  10. package/src/blob-upload.ts +165 -134
  11. package/src/blob-urls.ts +3 -5
  12. package/src/bootstrap-auth.ts +97 -0
  13. package/src/index.ts +3 -4
  14. package/src/lib.ts +14 -9
  15. package/src/runner.ts +23 -175
  16. package/src/tools/appscript.ts +1 -1
  17. package/src/tools/auth.ts +5 -5
  18. package/src/tools/drive.ts +1 -3
  19. package/src/tools/gmail.ts +9 -9
  20. package/src/tools/utils.ts +12 -58
  21. package/tests/attachments.test.ts +11 -14
  22. package/tests/blob-upload.test.ts +235 -160
  23. package/tests/bootstrap-auth.test.ts +245 -0
  24. package/tests/runner-file-args.test.ts +1 -13
  25. package/tests/runner.test.ts +8 -95
  26. package/tests/sdk-single-copy.test.ts +4 -12
  27. package/tests/tools/auth-401-shapes.test.ts +2 -3
  28. package/tests/tools/auth.test.ts +5 -4
  29. package/tests/tools/drive.test.ts +11 -3
  30. package/tests/tools/gmail.test.ts +2 -2
  31. package/tests/tools/utils.test.ts +1 -50
  32. package/tests/zod-single-copy.test.ts +6 -14
  33. package/tsconfig.json +1 -2
  34. package/vitest.config.ts +2 -12
  35. package/src/auth-log.ts +0 -205
  36. package/src/connector-auth.ts +0 -319
  37. package/src/connector-login.ts +0 -87
  38. package/src/connector-runtime.ts +0 -910
  39. package/src/google-probe.ts +0 -113
  40. package/src/google-token.ts +0 -391
  41. package/src/remote-runner.ts +0 -77
  42. package/src/worker.ts +0 -117
  43. package/tests/auth-log.test.ts +0 -530
  44. package/tests/connector-auth.test.ts +0 -559
  45. package/tests/connector-login.test.ts +0 -151
  46. package/tests/connector-runtime.test.ts +0 -1664
  47. package/tests/google-probe.test.ts +0 -116
  48. package/tests/google-token.test.ts +0 -425
  49. package/tests/remote-runner.test.ts +0 -202
  50. package/tests/worker.test.ts +0 -167
@@ -1,151 +0,0 @@
1
- import { describe, expect, it, vi } from 'vitest';
2
- import { handleAuthorize } from '../src/connector-login.js';
3
- import type { ConnectorAuth } from '../src/connector-auth.js';
4
-
5
- function encoded(value: unknown): string {
6
- return btoa(JSON.stringify(value));
7
- }
8
-
9
- function envFor(oauthReq: unknown = { clientId: 'client-1' }) {
10
- return {
11
- OAUTH_PROVIDER: {
12
- parseAuthRequest: vi.fn(async () => oauthReq),
13
- completeAuthorization: vi.fn(async () => ({ redirectTo: 'https://client.example/callback?code=ok' })),
14
- },
15
- };
16
- }
17
-
18
- const auth: ConnectorAuth<{ key: string }> = {
19
- service: 'gogcli <Workspace>',
20
- accent: '#4285F4',
21
- privacyNote: 'Stored & encrypted.',
22
- fields: [
23
- { name: 'key', label: 'Connector "key"', type: 'password' },
24
- { name: 'account', label: 'Account' },
25
- ],
26
- async login(fields) {
27
- return { key: fields.key };
28
- },
29
- };
30
-
31
- describe('connector login', () => {
32
- it('renders the parsed OAuth request in an escaped credential form', async () => {
33
- const env = envFor();
34
- const response = await handleAuthorize(new Request('https://connector.example/authorize'), env, auth);
35
-
36
- expect(response.status).toBe(200);
37
- expect(response.headers.get('content-type')).toContain('text/html');
38
- expect(env.OAUTH_PROVIDER.parseAuthRequest).toHaveBeenCalledOnce();
39
- const html = await response.text();
40
- expect(html).toContain('gogcli &lt;Workspace&gt;');
41
- expect(html).toContain('Connector &quot;key&quot;');
42
- expect(html).toContain('type="password"');
43
- expect(html).toContain('Stored &amp; encrypted.');
44
- expect(html).toContain(encoded({ clientId: 'client-1' }));
45
- });
46
-
47
- it('verifies submitted fields and completes authorization with an explicit user id', async () => {
48
- const env = envFor();
49
- const login = vi.fn(async () => ({ key: 'secret' }));
50
- const form = new FormData();
51
- form.set('oauthReq', encoded({ clientId: 'client-1' }));
52
- form.set('key', 'secret');
53
- form.set('account', 'person@example.com');
54
-
55
- const response = await handleAuthorize(
56
- new Request('https://connector.example/authorize', { method: 'POST', body: form }),
57
- env,
58
- { ...auth, userId: 'fixed-user', login },
59
- );
60
-
61
- expect(login).toHaveBeenCalledWith(
62
- { key: 'secret', account: 'person@example.com' },
63
- env,
64
- );
65
- expect(env.OAUTH_PROVIDER.completeAuthorization).toHaveBeenCalledWith({
66
- request: { clientId: 'client-1' },
67
- userId: 'fixed-user',
68
- scope: [],
69
- metadata: {},
70
- props: { key: 'secret' },
71
- });
72
- expect(response.status).toBe(302);
73
- expect(response.headers.get('location')).toBe('https://client.example/callback?code=ok');
74
- });
75
-
76
- it('uses the first credential as the user id and treats non-text fields as empty', async () => {
77
- const env = envFor();
78
- const login = vi.fn(async () => ({ key: 'secret' }));
79
- const form = new FormData();
80
- form.set('oauthReq', encoded({ clientId: 'client-1' }));
81
- form.set('key', 'secret');
82
- form.set('account', new Blob(['ignored']));
83
-
84
- await handleAuthorize(
85
- new Request('https://connector.example/authorize', { method: 'POST', body: form }),
86
- env,
87
- { ...auth, login },
88
- );
89
-
90
- expect(login).toHaveBeenCalledWith({ key: 'secret', account: '' }, env);
91
- expect(env.OAUTH_PROVIDER.completeAuthorization).toHaveBeenCalledWith(
92
- expect.objectContaining({ userId: 'secret' }),
93
- );
94
- });
95
-
96
- it('uses the public identity when there are no credential fields', async () => {
97
- const env = envFor();
98
- const form = new FormData();
99
- const login = vi.fn(async () => ({ key: 'public' }));
100
-
101
- await handleAuthorize(
102
- new Request('https://connector.example/authorize', { method: 'POST', body: form }),
103
- env,
104
- { service: 'Public', fields: [], login },
105
- );
106
-
107
- expect(env.OAUTH_PROVIDER.completeAuthorization).toHaveBeenCalledWith(
108
- expect.objectContaining({ request: undefined, userId: 'public' }),
109
- );
110
- });
111
-
112
- it('re-renders a safely escaped Error without completing authorization', async () => {
113
- const env = envFor();
114
- const form = new FormData();
115
- form.set('oauthReq', encoded({ clientId: 'client-1' }));
116
- form.set('key', 'bad');
117
- const response = await handleAuthorize(
118
- new Request('https://connector.example/authorize', { method: 'POST', body: form }),
119
- env,
120
- {
121
- service: 'gogcli',
122
- fields: [{ name: 'key', label: 'Key' }],
123
- async login() {
124
- throw new Error('bad <key>');
125
- },
126
- },
127
- );
128
-
129
- expect(response.status).toBe(200);
130
- expect(await response.text()).toContain('bad &lt;key&gt;');
131
- expect(env.OAUTH_PROVIDER.completeAuthorization).not.toHaveBeenCalled();
132
- });
133
-
134
- it('renders a non-Error rejection as text', async () => {
135
- const env = envFor();
136
- const form = new FormData();
137
- const response = await handleAuthorize(
138
- new Request('https://connector.example/authorize', { method: 'POST', body: form }),
139
- env,
140
- {
141
- service: 'gogcli',
142
- fields: [],
143
- async login() {
144
- throw 'try again';
145
- },
146
- },
147
- );
148
-
149
- expect(await response.text()).toContain('try again');
150
- });
151
- });