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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/index.js +273 -748
- package/dist/lib.js +375 -785
- package/manifest.json +2 -2
- package/mint.yaml +37 -33
- package/package.json +3 -3
- package/server.json +2 -2
- package/src/attachments.ts +28 -34
- package/src/blob-upload.ts +165 -134
- package/src/blob-urls.ts +3 -5
- package/src/bootstrap-auth.ts +97 -0
- package/src/index.ts +3 -4
- package/src/lib.ts +14 -9
- package/src/runner.ts +23 -175
- package/src/tools/appscript.ts +1 -1
- package/src/tools/auth.ts +5 -5
- package/src/tools/drive.ts +1 -3
- package/src/tools/gmail.ts +9 -9
- package/src/tools/utils.ts +12 -58
- package/tests/attachments.test.ts +11 -14
- package/tests/blob-upload.test.ts +235 -160
- package/tests/bootstrap-auth.test.ts +245 -0
- package/tests/runner-file-args.test.ts +1 -13
- package/tests/runner.test.ts +8 -95
- package/tests/sdk-single-copy.test.ts +4 -12
- package/tests/tools/auth-401-shapes.test.ts +2 -3
- package/tests/tools/auth.test.ts +5 -4
- package/tests/tools/drive.test.ts +11 -3
- package/tests/tools/gmail.test.ts +2 -2
- package/tests/tools/utils.test.ts +1 -50
- package/tests/zod-single-copy.test.ts +6 -14
- package/tsconfig.json +1 -2
- package/vitest.config.ts +2 -12
- package/src/auth-log.ts +0 -205
- package/src/connector-auth.ts +0 -319
- package/src/connector-login.ts +0 -87
- package/src/connector-runtime.ts +0 -910
- package/src/google-probe.ts +0 -113
- package/src/google-token.ts +0 -391
- package/src/remote-runner.ts +0 -77
- package/src/worker.ts +0 -117
- package/tests/auth-log.test.ts +0 -530
- package/tests/connector-auth.test.ts +0 -559
- package/tests/connector-login.test.ts +0 -151
- package/tests/connector-runtime.test.ts +0 -1664
- package/tests/google-probe.test.ts +0 -116
- package/tests/google-token.test.ts +0 -425
- package/tests/remote-runner.test.ts +0 -202
- 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 <Workspace>');
|
|
41
|
-
expect(html).toContain('Connector "key"');
|
|
42
|
-
expect(html).toContain('type="password"');
|
|
43
|
-
expect(html).toContain('Stored & 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 <key>');
|
|
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
|
-
});
|