@aaronsb/google-workspace-mcp 2.7.1 → 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/LICENSE +201 -21
- package/LICENSE-MIT +21 -0
- package/NOTICE +24 -0
- package/README.md +87 -57
- package/build/accounts/auth.d.ts +1 -1
- package/build/accounts/auth.js +1 -1
- package/build/accounts/oauth.js +3 -3
- package/build/accounts/oauth.js.map +1 -1
- package/build/accounts/token-service.js +1 -1
- package/build/accounts/token-service.js.map +1 -1
- package/build/coverage/analyze.d.ts +1 -1
- package/build/coverage/analyze.js +6 -4
- package/build/coverage/analyze.js.map +1 -1
- package/build/coverage/baseline.js +37 -20
- package/build/coverage/baseline.js.map +1 -1
- package/build/coverage/compare.d.ts +1 -1
- package/build/coverage/compare.js +19 -10
- package/build/coverage/compare.js.map +1 -1
- package/build/coverage/discover.d.ts +5 -5
- package/build/coverage/discover.js +71 -155
- package/build/coverage/discover.js.map +1 -1
- package/build/coverage/report.js +3 -3
- package/build/coverage/report.js.map +1 -1
- package/build/coverage/types.d.ts +19 -4
- package/build/executor/index.d.ts +0 -3
- package/build/executor/index.js +1 -2
- package/build/executor/index.js.map +1 -1
- package/build/factory/defaults.js +30 -4
- package/build/factory/defaults.js.map +1 -1
- package/build/factory/generator.d.ts +10 -4
- package/build/factory/generator.js +86 -96
- package/build/factory/generator.js.map +1 -1
- package/build/factory/manifest/README.md +4 -3
- package/build/factory/manifest/calendar.yaml +1 -11
- package/build/factory/manifest/docs.yaml +15 -6
- package/build/factory/manifest/drive.yaml +1 -5
- package/build/factory/manifest/gmail.yaml +32 -25
- package/build/factory/manifest/meet.yaml +1 -1
- package/build/factory/manifest/sheets.yaml +2 -5
- package/build/factory/manifest/tasks.yaml +40 -2
- package/build/factory/patches.js +2 -0
- package/build/factory/patches.js.map +1 -1
- package/build/factory/registry.d.ts +2 -3
- package/build/factory/registry.js +3 -9
- package/build/factory/registry.js.map +1 -1
- package/build/factory/safety.js +4 -4
- package/build/factory/safety.js.map +1 -1
- package/build/factory/types.d.ts +16 -15
- package/build/google/client.d.ts +45 -0
- package/build/google/client.js +232 -0
- package/build/google/client.js.map +1 -0
- package/build/google/descriptor.d.ts +40 -0
- package/build/google/descriptor.js +37 -0
- package/build/google/descriptor.js.map +1 -0
- package/build/google/descriptor.json +5271 -0
- package/build/google/errors.d.ts +45 -0
- package/build/google/errors.js +44 -0
- package/build/google/errors.js.map +1 -0
- package/build/google/methods.d.ts +37 -0
- package/build/google/methods.js +13 -0
- package/build/google/methods.js.map +1 -0
- package/build/index.js +30 -4
- package/build/index.js.map +1 -1
- package/build/node-floor.d.ts +16 -0
- package/build/node-floor.js +73 -0
- package/build/node-floor.js.map +1 -0
- package/build/server/formatting/markdown.d.ts +1 -1
- package/build/server/formatting/markdown.js +1 -1
- package/build/server/formatting/next-steps.js +1 -1
- package/build/server/formatting/next-steps.js.map +1 -1
- package/build/server/handlers/accounts.js +2 -2
- package/build/server/handlers/accounts.js.map +1 -1
- package/build/server/scratchpad/adapters/import-doc.js +15 -13
- package/build/server/scratchpad/adapters/import-doc.js.map +1 -1
- package/build/server/scratchpad/adapters/import-drive.js +16 -11
- package/build/server/scratchpad/adapters/import-drive.js.map +1 -1
- package/build/server/scratchpad/adapters/import-email.js +3 -15
- package/build/server/scratchpad/adapters/import-email.js.map +1 -1
- package/build/server/scratchpad/adapters/import-meet.js +5 -17
- package/build/server/scratchpad/adapters/import-meet.js.map +1 -1
- package/build/server/scratchpad/adapters/import-sheet.js +5 -6
- package/build/server/scratchpad/adapters/import-sheet.js.map +1 -1
- package/build/server/scratchpad/adapters/send-calendar.js +18 -13
- package/build/server/scratchpad/adapters/send-calendar.js.map +1 -1
- package/build/server/scratchpad/adapters/send-doc.js +22 -17
- package/build/server/scratchpad/adapters/send-doc.js.map +1 -1
- package/build/server/scratchpad/adapters/send-email-draft.d.ts +1 -1
- package/build/server/scratchpad/adapters/send-email-draft.js +17 -25
- package/build/server/scratchpad/adapters/send-email-draft.js.map +1 -1
- package/build/server/scratchpad/adapters/send-email.d.ts +2 -2
- package/build/server/scratchpad/adapters/send-email.js +21 -25
- package/build/server/scratchpad/adapters/send-email.js.map +1 -1
- package/build/server/scratchpad/adapters/send-sheet.js +10 -10
- package/build/server/scratchpad/adapters/send-sheet.js.map +1 -1
- package/build/server/scratchpad/adapters/send-task.js +9 -8
- package/build/server/scratchpad/adapters/send-task.js.map +1 -1
- package/build/server/scratchpad/handler.js +22 -28
- package/build/server/scratchpad/handler.js.map +1 -1
- package/build/server/scratchpad/manager.d.ts +1 -1
- package/build/server/server.js +13 -10
- package/build/server/server.js.map +1 -1
- package/build/server/session/tracker.js +21 -25
- package/build/server/session/tracker.js.map +1 -1
- package/build/server/tools.d.ts +1 -1
- package/build/server/tools.js +3 -3
- package/build/server/tools.js.map +1 -1
- package/build/services/calendar/patch.js +178 -68
- package/build/services/calendar/patch.js.map +1 -1
- package/build/services/docs/patch.d.ts +5 -3
- package/build/services/docs/patch.js +89 -19
- package/build/services/docs/patch.js.map +1 -1
- package/build/services/drive/patch.d.ts +1 -1
- package/build/services/drive/patch.js +115 -143
- package/build/services/drive/patch.js.map +1 -1
- package/build/services/gmail/attachments.js +10 -15
- package/build/services/gmail/attachments.js.map +1 -1
- package/build/services/gmail/mail.d.ts +34 -0
- package/build/services/gmail/mail.js +245 -0
- package/build/services/gmail/mail.js.map +1 -0
- package/build/services/gmail/mime.d.ts +45 -4
- package/build/services/gmail/mime.js +138 -4
- package/build/services/gmail/mime.js.map +1 -1
- package/build/services/gmail/patch.js +103 -53
- package/build/services/gmail/patch.js.map +1 -1
- package/build/services/meet/patch.js +24 -31
- package/build/services/meet/patch.js.map +1 -1
- package/build/services/sheets/patch.js +30 -35
- package/build/services/sheets/patch.js.map +1 -1
- package/build/services/tasks/patch.d.ts +18 -0
- package/build/services/tasks/patch.js +37 -0
- package/build/services/tasks/patch.js.map +1 -0
- package/build/version.d.ts +1 -1
- package/build/version.js +2 -2
- package/build/version.js.map +1 -1
- package/package.json +23 -12
- package/build/__helpers__/testSetup.d.ts +0 -1
- package/build/__helpers__/testSetup.js +0 -6
- package/build/__helpers__/testSetup.js.map +0 -1
- package/build/__tests__/accounts/credentials.test.d.ts +0 -1
- package/build/__tests__/accounts/credentials.test.js +0 -127
- package/build/__tests__/accounts/credentials.test.js.map +0 -1
- package/build/__tests__/accounts/oauth.test.d.ts +0 -1
- package/build/__tests__/accounts/oauth.test.js +0 -71
- package/build/__tests__/accounts/oauth.test.js.map +0 -1
- package/build/__tests__/accounts/registry.test.d.ts +0 -1
- package/build/__tests__/accounts/registry.test.js +0 -74
- package/build/__tests__/accounts/registry.test.js.map +0 -1
- package/build/__tests__/accounts/token-service.test.d.ts +0 -1
- package/build/__tests__/accounts/token-service.test.js +0 -126
- package/build/__tests__/accounts/token-service.test.js.map +0 -1
- package/build/__tests__/executor/errors.test.d.ts +0 -1
- package/build/__tests__/executor/errors.test.js +0 -42
- package/build/__tests__/executor/errors.test.js.map +0 -1
- package/build/__tests__/executor/gws.test.d.ts +0 -1
- package/build/__tests__/executor/gws.test.js +0 -187
- package/build/__tests__/executor/gws.test.js.map +0 -1
- package/build/__tests__/executor/paths.test.d.ts +0 -1
- package/build/__tests__/executor/paths.test.js +0 -60
- package/build/__tests__/executor/paths.test.js.map +0 -1
- package/build/__tests__/executor/resolve-binary.test.d.ts +0 -1
- package/build/__tests__/executor/resolve-binary.test.js +0 -58
- package/build/__tests__/executor/resolve-binary.test.js.map +0 -1
- package/build/__tests__/executor/workspace.test.d.ts +0 -1
- package/build/__tests__/executor/workspace.test.js +0 -143
- package/build/__tests__/executor/workspace.test.js.map +0 -1
- package/build/__tests__/factory/calendar-patch.test.d.ts +0 -5
- package/build/__tests__/factory/calendar-patch.test.js +0 -269
- package/build/__tests__/factory/calendar-patch.test.js.map +0 -1
- package/build/__tests__/factory/drive-patch.test.d.ts +0 -5
- package/build/__tests__/factory/drive-patch.test.js +0 -344
- package/build/__tests__/factory/drive-patch.test.js.map +0 -1
- package/build/__tests__/factory/generator.test.d.ts +0 -1
- package/build/__tests__/factory/generator.test.js +0 -240
- package/build/__tests__/factory/generator.test.js.map +0 -1
- package/build/__tests__/factory/patch-coverage.test.d.ts +0 -10
- package/build/__tests__/factory/patch-coverage.test.js +0 -182
- package/build/__tests__/factory/patch-coverage.test.js.map +0 -1
- package/build/__tests__/factory/safety.test.d.ts +0 -1
- package/build/__tests__/factory/safety.test.js +0 -107
- package/build/__tests__/factory/safety.test.js.map +0 -1
- package/build/__tests__/factory/sheets-patch.test.d.ts +0 -6
- package/build/__tests__/factory/sheets-patch.test.js +0 -498
- package/build/__tests__/factory/sheets-patch.test.js.map +0 -1
- package/build/__tests__/integration/executor.test.d.ts +0 -5
- package/build/__tests__/integration/executor.test.js +0 -38
- package/build/__tests__/integration/executor.test.js.map +0 -1
- package/build/__tests__/integration/handlers.test.d.ts +0 -6
- package/build/__tests__/integration/handlers.test.js +0 -95
- package/build/__tests__/integration/handlers.test.js.map +0 -1
- package/build/__tests__/integration/setup.d.ts +0 -19
- package/build/__tests__/integration/setup.js +0 -61
- package/build/__tests__/integration/setup.js.map +0 -1
- package/build/__tests__/server/formatting/html-sanitize.test.d.ts +0 -7
- package/build/__tests__/server/formatting/html-sanitize.test.js +0 -174
- package/build/__tests__/server/formatting/html-sanitize.test.js.map +0 -1
- package/build/__tests__/server/formatting/markdown.test.d.ts +0 -1
- package/build/__tests__/server/formatting/markdown.test.js +0 -259
- package/build/__tests__/server/formatting/markdown.test.js.map +0 -1
- package/build/__tests__/server/formatting/next-steps.test.d.ts +0 -1
- package/build/__tests__/server/formatting/next-steps.test.js +0 -42
- package/build/__tests__/server/formatting/next-steps.test.js.map +0 -1
- package/build/__tests__/server/handler.test.d.ts +0 -1
- package/build/__tests__/server/handler.test.js +0 -97
- package/build/__tests__/server/handler.test.js.map +0 -1
- package/build/__tests__/server/handlers/__mocks__/executor.d.ts +0 -173
- package/build/__tests__/server/handlers/__mocks__/executor.js +0 -135
- package/build/__tests__/server/handlers/__mocks__/executor.js.map +0 -1
- package/build/__tests__/server/handlers/accounts.test.d.ts +0 -1
- package/build/__tests__/server/handlers/accounts.test.js +0 -129
- package/build/__tests__/server/handlers/accounts.test.js.map +0 -1
- package/build/__tests__/server/handlers/calendar.test.d.ts +0 -1
- package/build/__tests__/server/handlers/calendar.test.js +0 -96
- package/build/__tests__/server/handlers/calendar.test.js.map +0 -1
- package/build/__tests__/server/handlers/drive.test.d.ts +0 -1
- package/build/__tests__/server/handlers/drive.test.js +0 -68
- package/build/__tests__/server/handlers/drive.test.js.map +0 -1
- package/build/__tests__/server/handlers/email.test.d.ts +0 -1
- package/build/__tests__/server/handlers/email.test.js +0 -99
- package/build/__tests__/server/handlers/email.test.js.map +0 -1
- package/build/__tests__/server/handlers/validate.test.d.ts +0 -1
- package/build/__tests__/server/handlers/validate.test.js +0 -88
- package/build/__tests__/server/handlers/validate.test.js.map +0 -1
- package/build/__tests__/server/queue.test.d.ts +0 -1
- package/build/__tests__/server/queue.test.js +0 -199
- package/build/__tests__/server/queue.test.js.map +0 -1
- package/build/__tests__/server/server.test.d.ts +0 -7
- package/build/__tests__/server/server.test.js +0 -135
- package/build/__tests__/server/server.test.js.map +0 -1
- package/build/__tests__/server/session/context.test.d.ts +0 -1
- package/build/__tests__/server/session/context.test.js +0 -101
- package/build/__tests__/server/session/context.test.js.map +0 -1
- package/build/__tests__/server/session/tracker.test.d.ts +0 -1
- package/build/__tests__/server/session/tracker.test.js +0 -146
- package/build/__tests__/server/session/tracker.test.js.map +0 -1
- package/build/__tests__/server/tools.test.d.ts +0 -1
- package/build/__tests__/server/tools.test.js +0 -91
- package/build/__tests__/server/tools.test.js.map +0 -1
- package/build/__tests__/services/gmail/mime.test.d.ts +0 -1
- package/build/__tests__/services/gmail/mime.test.js +0 -23
- package/build/__tests__/services/gmail/mime.test.js.map +0 -1
- package/build/__tests__/services/meet/patch.test.d.ts +0 -4
- package/build/__tests__/services/meet/patch.test.js +0 -374
- package/build/__tests__/services/meet/patch.test.js.map +0 -1
- package/build/executor/errors.d.ts +0 -15
- package/build/executor/errors.js +0 -37
- package/build/executor/errors.js.map +0 -1
- package/build/executor/gws.d.ts +0 -26
- package/build/executor/gws.js +0 -197
- package/build/executor/gws.js.map +0 -1
- package/build/server/handlers/calendar.d.ts +0 -2
- package/build/server/handlers/calendar.js +0 -97
- package/build/server/handlers/calendar.js.map +0 -1
- package/build/server/handlers/drive.d.ts +0 -2
- package/build/server/handlers/drive.js +0 -58
- package/build/server/handlers/drive.js.map +0 -1
- package/build/server/handlers/email.d.ts +0 -2
- package/build/server/handlers/email.js +0 -119
- package/build/server/handlers/email.js.map +0 -1
- package/build/server/scratchpad/__tests__/docs-sync-integration.test.d.ts +0 -11
- package/build/server/scratchpad/__tests__/docs-sync-integration.test.js +0 -187
- package/build/server/scratchpad/__tests__/docs-sync-integration.test.js.map +0 -1
- package/build/server/scratchpad/__tests__/docs-sync.test.d.ts +0 -16
- package/build/server/scratchpad/__tests__/docs-sync.test.js +0 -213
- package/build/server/scratchpad/__tests__/docs-sync.test.js.map +0 -1
- package/build/server/scratchpad/__tests__/json-path.test.d.ts +0 -4
- package/build/server/scratchpad/__tests__/json-path.test.js +0 -121
- package/build/server/scratchpad/__tests__/json-path.test.js.map +0 -1
- package/build/server/scratchpad/__tests__/manager.test.d.ts +0 -5
- package/build/server/scratchpad/__tests__/manager.test.js +0 -886
- package/build/server/scratchpad/__tests__/manager.test.js.map +0 -1
- package/build/server/scratchpad/__tests__/validate.test.d.ts +0 -4
- package/build/server/scratchpad/__tests__/validate.test.js +0 -112
- package/build/server/scratchpad/__tests__/validate.test.js.map +0 -1
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Google API client.
|
|
3
|
+
*
|
|
4
|
+
* The whole of a resource operation: get a token, make the call, hand back the JSON.
|
|
5
|
+
*
|
|
6
|
+
* LOAD-BEARING CONSTRAINT — this layer has NO OPINIONS. It never reshapes, never
|
|
7
|
+
* "fixes", never fills in. It returns exactly what Google returned. Interpretation
|
|
8
|
+
* happens ABOVE it, in the layer we already own and aim at the MCP contract
|
|
9
|
+
* (patches / formatters / next-steps). The moment this file gets helpful, it
|
|
10
|
+
* becomes something that can be subtly wrong in a way no test catches — the exact
|
|
11
|
+
* defect class ADR-101 spent six review rounds learning to fear.
|
|
12
|
+
*
|
|
13
|
+
* Everything here is a consequence of something the DESCRIPTOR said. Where a rule
|
|
14
|
+
* looks arbitrary, it is not: it is a fact we learned by being wrong first, live,
|
|
15
|
+
* against Google (ADR-103, item 2).
|
|
16
|
+
*
|
|
17
|
+
* See ADR-103.
|
|
18
|
+
*/
|
|
19
|
+
import { createWriteStream } from 'node:fs';
|
|
20
|
+
import { mkdir } from 'node:fs/promises';
|
|
21
|
+
import { dirname } from 'node:path';
|
|
22
|
+
import { Readable } from 'node:stream';
|
|
23
|
+
import { pipeline } from 'node:stream/promises';
|
|
24
|
+
import { getAccessToken } from '../accounts/token-service.js';
|
|
25
|
+
import { GoogleApiError } from './errors.js';
|
|
26
|
+
import { loadDescriptor } from './descriptor.js';
|
|
27
|
+
function resolve(descriptor, service, resourcePath) {
|
|
28
|
+
const svc = descriptor.services[service];
|
|
29
|
+
if (!svc)
|
|
30
|
+
throw new Error(`descriptor has no service '${service}'`);
|
|
31
|
+
const method = svc.methods[resourcePath];
|
|
32
|
+
if (!method)
|
|
33
|
+
throw new Error(`descriptor has no method '${service}.${resourcePath}'`);
|
|
34
|
+
return { svc, method };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Expand a path template.
|
|
38
|
+
*
|
|
39
|
+
* `{+var}` is RFC 6570 RESERVED expansion — reserved characters, notably `/`,
|
|
40
|
+
* must NOT be percent-encoded. Meet's identifiers ARE paths
|
|
41
|
+
* ("conferenceRecords/abc"), so encoding that slash to %2F 404s every Meet
|
|
42
|
+
* sub-resource operation. The `+` is the descriptor telling us this. Honour it.
|
|
43
|
+
*/
|
|
44
|
+
function expandPath(template, pathParams) {
|
|
45
|
+
return template.replace(/\{(\+?)([^}]+)\}/g, (_m, reserved, name) => {
|
|
46
|
+
if (!(name in pathParams))
|
|
47
|
+
throw new Error(`missing required path param '${name}'`);
|
|
48
|
+
const raw = String(pathParams[name]);
|
|
49
|
+
return reserved
|
|
50
|
+
? raw.split('/').map(encodeURIComponent).join('/')
|
|
51
|
+
: encodeURIComponent(raw);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Split params into path / query / body by what the descriptor DECLARES.
|
|
56
|
+
*
|
|
57
|
+
* Global parameters (`fields`, `alt`, `quotaUser`, `prettyPrint`) are declared
|
|
58
|
+
* ONCE at the document root, not per method. A dispatcher that consults only the
|
|
59
|
+
* method's parameters cannot place `fields`, drops it into the body, and a GET
|
|
60
|
+
* silently discards it — which is exactly how drive.listComments died with
|
|
61
|
+
* "The 'fields' parameter is required". Merge both; the method wins on conflict.
|
|
62
|
+
*/
|
|
63
|
+
function splitParams(svc, method, params) {
|
|
64
|
+
const declared = { ...svc.globalParameters, ...method.parameters };
|
|
65
|
+
const path = {};
|
|
66
|
+
const query = {};
|
|
67
|
+
const body = {};
|
|
68
|
+
for (const [key, value] of Object.entries(params)) {
|
|
69
|
+
if (value === undefined || value === null)
|
|
70
|
+
continue;
|
|
71
|
+
const location = declared[key]?.location;
|
|
72
|
+
if (location === 'path')
|
|
73
|
+
path[key] = value;
|
|
74
|
+
else if (location === 'query')
|
|
75
|
+
query[key] = value;
|
|
76
|
+
else
|
|
77
|
+
body[key] = value; // undeclared -> request body; Google validates it, not us
|
|
78
|
+
}
|
|
79
|
+
return { path, query, body };
|
|
80
|
+
}
|
|
81
|
+
function applyQuery(url, query) {
|
|
82
|
+
for (const [key, value] of Object.entries(query)) {
|
|
83
|
+
if (Array.isArray(value))
|
|
84
|
+
value.forEach((v) => url.searchParams.append(key, String(v)));
|
|
85
|
+
else
|
|
86
|
+
url.searchParams.set(key, String(value));
|
|
87
|
+
}
|
|
88
|
+
return url;
|
|
89
|
+
}
|
|
90
|
+
/** Pure: descriptor + params -> the request. No I/O, so it is testable offline. */
|
|
91
|
+
export function buildRequest(descriptor, service, resourcePath, params = {}) {
|
|
92
|
+
const { svc, method } = resolve(descriptor, service, resourcePath);
|
|
93
|
+
const { path, query, body } = splitParams(svc, method, params);
|
|
94
|
+
const base = svc.rootUrl.replace(/\/$/, '') + '/' + svc.servicePath.replace(/^\//, '');
|
|
95
|
+
const url = applyQuery(new URL((base.replace(/\/$/, '') + '/' + expandPath(method.path, path)).replace(/\/+$/, '')), query);
|
|
96
|
+
const hasBody = Object.keys(body).length > 0 && method.httpMethod !== 'GET';
|
|
97
|
+
return { url: url.toString(), method: method.httpMethod, body: hasBody ? body : undefined };
|
|
98
|
+
}
|
|
99
|
+
function parseJson(text) {
|
|
100
|
+
if (!text)
|
|
101
|
+
return {};
|
|
102
|
+
try {
|
|
103
|
+
return JSON.parse(text);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return { error: { message: text.slice(0, 300) } };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Call a Google API method. Returns RAW Google JSON — no envelope, no reshaping.
|
|
111
|
+
* Throws GoogleApiError carrying Google's real error body.
|
|
112
|
+
*/
|
|
113
|
+
export async function call(service, resourcePath, params, options) {
|
|
114
|
+
const descriptor = options.descriptor ?? await loadDescriptor();
|
|
115
|
+
const doFetch = options.fetchImpl ?? fetch;
|
|
116
|
+
const request = buildRequest(descriptor, service, resourcePath, params);
|
|
117
|
+
const token = await getAccessToken(options.account);
|
|
118
|
+
const response = await doFetch(request.url, {
|
|
119
|
+
method: request.method,
|
|
120
|
+
headers: {
|
|
121
|
+
Authorization: `Bearer ${token}`,
|
|
122
|
+
...(request.body ? { 'Content-Type': 'application/json' } : {}),
|
|
123
|
+
},
|
|
124
|
+
...(request.body ? { body: JSON.stringify(request.body) } : {}),
|
|
125
|
+
});
|
|
126
|
+
const text = await response.text();
|
|
127
|
+
const json = parseJson(text);
|
|
128
|
+
if (!response.ok) {
|
|
129
|
+
throw new GoogleApiError(response.status, json, {
|
|
130
|
+
url: request.url,
|
|
131
|
+
method: request.method,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return json;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Download media to disk.
|
|
138
|
+
*
|
|
139
|
+
* STREAMED, deliberately. The bytes go from the socket to the file and are never a
|
|
140
|
+
* string at all. Never buffer a download through an in-memory string: accumulating
|
|
141
|
+
* the whole response and JSON.parse-ing it turns a 30 MB attachment into a ~40 MB
|
|
142
|
+
* string, then an object, then a Buffer — uncapped, for every download.
|
|
143
|
+
*/
|
|
144
|
+
export async function download(service, resourcePath, params, outputPath, options) {
|
|
145
|
+
const descriptor = options.descriptor ?? await loadDescriptor();
|
|
146
|
+
const doFetch = options.fetchImpl ?? fetch;
|
|
147
|
+
const request = buildRequest(descriptor, service, resourcePath, params);
|
|
148
|
+
const token = await getAccessToken(options.account);
|
|
149
|
+
const response = await doFetch(request.url, {
|
|
150
|
+
method: request.method,
|
|
151
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
152
|
+
});
|
|
153
|
+
if (!response.ok) {
|
|
154
|
+
const json = parseJson(await response.text());
|
|
155
|
+
throw new GoogleApiError(response.status, json, {
|
|
156
|
+
url: request.url,
|
|
157
|
+
method: request.method,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (!response.body)
|
|
161
|
+
throw new Error(`no response body for ${service}.${resourcePath}`);
|
|
162
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
163
|
+
await pipeline(Readable.fromWeb(response.body), createWriteStream(outputPath));
|
|
164
|
+
return outputPath;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Resumable, chunked media upload.
|
|
168
|
+
*
|
|
169
|
+
* The descriptor carries the upload paths for both protocols because Discovery
|
|
170
|
+
* DECLARES them. Verified live (ADR-103 item 4): a 25 MB attachment — 34.2 MB as
|
|
171
|
+
* RFC822, 93% of Google's declared 36,700,160-byte cap — uploaded in 5 chunks and
|
|
172
|
+
* read back byte-for-byte identical.
|
|
173
|
+
*/
|
|
174
|
+
export async function upload(service, resourcePath, params, options) {
|
|
175
|
+
const descriptor = options.descriptor ?? await loadDescriptor();
|
|
176
|
+
const doFetch = options.fetchImpl ?? fetch;
|
|
177
|
+
const { svc, method } = resolve(descriptor, service, resourcePath);
|
|
178
|
+
if (!method.mediaUpload)
|
|
179
|
+
throw new Error(`${service}.${resourcePath} does not support media upload`);
|
|
180
|
+
// Google DECLARES the ceiling. Refusing locally beats a confusing 400 from a
|
|
181
|
+
// 35 MB request that already crossed the wire.
|
|
182
|
+
const max = Number(method.mediaUpload.maxSize);
|
|
183
|
+
if (max && options.media.length > max) {
|
|
184
|
+
throw new Error(`${service}.${resourcePath}: payload is ${options.media.length} bytes; ` +
|
|
185
|
+
`Google's declared limit is ${max} bytes`);
|
|
186
|
+
}
|
|
187
|
+
const token = await getAccessToken(options.account);
|
|
188
|
+
const { path, query } = splitParams(svc, method, params);
|
|
189
|
+
const uploadPath = method.mediaUpload.resumable ?? method.mediaUpload.simple;
|
|
190
|
+
if (!uploadPath)
|
|
191
|
+
throw new Error(`${service}.${resourcePath} declares no upload protocol`);
|
|
192
|
+
const initiateUrl = applyQuery(new URL(expandPath(uploadPath, path), svc.rootUrl), { ...query, uploadType: 'resumable' }).toString();
|
|
193
|
+
const initiate = await doFetch(initiateUrl, {
|
|
194
|
+
method: method.httpMethod,
|
|
195
|
+
headers: {
|
|
196
|
+
Authorization: `Bearer ${token}`,
|
|
197
|
+
'Content-Type': 'application/json; charset=UTF-8',
|
|
198
|
+
'X-Upload-Content-Type': options.contentType,
|
|
199
|
+
'X-Upload-Content-Length': String(options.media.length),
|
|
200
|
+
},
|
|
201
|
+
body: JSON.stringify(options.metadata ?? {}),
|
|
202
|
+
});
|
|
203
|
+
if (!initiate.ok) {
|
|
204
|
+
const json = parseJson(await initiate.text());
|
|
205
|
+
throw new GoogleApiError(initiate.status, json, { url: initiateUrl, method: method.httpMethod });
|
|
206
|
+
}
|
|
207
|
+
const session = initiate.headers.get('location');
|
|
208
|
+
if (!session)
|
|
209
|
+
throw new Error('resumable upload: initiate returned no Location header');
|
|
210
|
+
const chunkSize = options.chunkSize ?? 8 * 1024 * 1024;
|
|
211
|
+
let offset = 0;
|
|
212
|
+
while (offset < options.media.length) {
|
|
213
|
+
const end = Math.min(offset + chunkSize, options.media.length);
|
|
214
|
+
const response = await doFetch(session, {
|
|
215
|
+
method: 'PUT',
|
|
216
|
+
headers: { 'Content-Range': `bytes ${offset}-${end - 1}/${options.media.length}` },
|
|
217
|
+
body: options.media.subarray(offset, end),
|
|
218
|
+
});
|
|
219
|
+
// 308 "Resume Incomplete" is the protocol working, not an error.
|
|
220
|
+
if (response.status === 308) {
|
|
221
|
+
offset = end;
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
const text = await response.text();
|
|
225
|
+
if (!response.ok) {
|
|
226
|
+
throw new GoogleApiError(response.status, parseJson(text), { url: session, method: 'PUT' });
|
|
227
|
+
}
|
|
228
|
+
return parseJson(text);
|
|
229
|
+
}
|
|
230
|
+
throw new Error('resumable upload: media consumed without a terminal response');
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/google/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface ApiParam {
|
|
2
|
+
location: 'path' | 'query';
|
|
3
|
+
required?: boolean;
|
|
4
|
+
repeated?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface ApiMediaUpload {
|
|
7
|
+
maxSize?: string;
|
|
8
|
+
accept?: string[];
|
|
9
|
+
simple?: string;
|
|
10
|
+
resumable?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ApiMethod {
|
|
13
|
+
path: string;
|
|
14
|
+
httpMethod: string;
|
|
15
|
+
parameters: Record<string, ApiParam>;
|
|
16
|
+
scopes?: string[];
|
|
17
|
+
supportsMediaDownload?: boolean;
|
|
18
|
+
mediaUpload?: ApiMediaUpload;
|
|
19
|
+
}
|
|
20
|
+
export interface ApiService {
|
|
21
|
+
version: string;
|
|
22
|
+
rootUrl: string;
|
|
23
|
+
servicePath: string;
|
|
24
|
+
discoveryUrl: string;
|
|
25
|
+
/** `fields`, `alt`, `quotaUser`… declared once at the document root, not per method. */
|
|
26
|
+
globalParameters: Record<string, ApiParam>;
|
|
27
|
+
methods: Record<string, ApiMethod>;
|
|
28
|
+
}
|
|
29
|
+
export interface ApiDescriptor {
|
|
30
|
+
generatedFrom: string;
|
|
31
|
+
services: Record<string, ApiService>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Load the descriptor. Resolved as a sibling of this module, which makes it work
|
|
35
|
+
* under `src/` (vitest) and under `build/` (the shipped server) alike — the same
|
|
36
|
+
* trick `loadManifest()` uses, and the reason `npx` works.
|
|
37
|
+
*/
|
|
38
|
+
export declare function loadDescriptor(): Promise<ApiDescriptor>;
|
|
39
|
+
/** Tests only: drop the memoised descriptor. */
|
|
40
|
+
export declare function resetDescriptorCache(): void;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The API descriptor: a generated, committed transcription of Google's Discovery
|
|
3
|
+
* documents, pruned to what making a REQUEST needs.
|
|
4
|
+
*
|
|
5
|
+
* Generated at BUILD time by `scripts/generate-descriptor.mjs` and committed, so
|
|
6
|
+
* there is no network dependency at startup and nothing breaks offline. Drift is a
|
|
7
|
+
* CI check, not a production surprise.
|
|
8
|
+
*
|
|
9
|
+
* It records what Discovery says about how to CALL Google. It records nothing
|
|
10
|
+
* about what a RESPONSE means — Discovery's `schemas` block (~90% of the raw
|
|
11
|
+
* document) is deliberately DISCARDED. A descriptor that knows response shapes is
|
|
12
|
+
* a descriptor that can start helpfully reshaping them.
|
|
13
|
+
*
|
|
14
|
+
* See ADR-103.
|
|
15
|
+
*/
|
|
16
|
+
import { readFile } from 'node:fs/promises';
|
|
17
|
+
import { dirname, resolve } from 'node:path';
|
|
18
|
+
import { fileURLToPath } from 'node:url';
|
|
19
|
+
let cached;
|
|
20
|
+
/**
|
|
21
|
+
* Load the descriptor. Resolved as a sibling of this module, which makes it work
|
|
22
|
+
* under `src/` (vitest) and under `build/` (the shipped server) alike — the same
|
|
23
|
+
* trick `loadManifest()` uses, and the reason `npx` works.
|
|
24
|
+
*/
|
|
25
|
+
export async function loadDescriptor() {
|
|
26
|
+
if (cached)
|
|
27
|
+
return cached;
|
|
28
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
29
|
+
const raw = await readFile(resolve(here, 'descriptor.json'), 'utf-8');
|
|
30
|
+
cached = JSON.parse(raw);
|
|
31
|
+
return cached;
|
|
32
|
+
}
|
|
33
|
+
/** Tests only: drop the memoised descriptor. */
|
|
34
|
+
export function resetDescriptorCache() {
|
|
35
|
+
cached = undefined;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=descriptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"descriptor.js","sourceRoot":"","sources":["../../src/google/descriptor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAuCzC,IAAI,MAAiC,CAAC;AAEtC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAAC;IACtE,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkB,CAAC;IAC1C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,oBAAoB;IAClC,MAAM,GAAG,SAAS,CAAC;AACrB,CAAC"}
|