@fluxmail/core 0.18.0 → 0.19.1
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/dist/attachments.d.ts +9 -0
- package/dist/attachments.d.ts.map +1 -0
- package/dist/attachments.js +27 -0
- package/dist/attachments.js.map +1 -0
- package/dist/errors.d.ts +5 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +16 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/clients.d.ts +16 -0
- package/dist/mcp/clients.d.ts.map +1 -0
- package/dist/mcp/clients.js +69 -0
- package/dist/mcp/clients.js.map +1 -0
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +2 -0
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/pdf.d.ts +18 -0
- package/dist/mcp/pdf.d.ts.map +1 -0
- package/dist/mcp/pdf.js +97 -0
- package/dist/mcp/pdf.js.map +1 -0
- package/dist/mcp/results.d.ts +114 -0
- package/dist/mcp/results.d.ts.map +1 -0
- package/dist/mcp/results.js +165 -0
- package/dist/mcp/results.js.map +1 -0
- package/dist/mcp/tools.d.ts +11 -3
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.generated.d.ts +1 -0
- package/dist/mcp/tools.generated.d.ts.map +1 -1
- package/dist/mcp/tools.generated.js +2184 -33
- package/dist/mcp/tools.generated.js.map +1 -1
- package/dist/mcp/tools.js +9 -1
- package/dist/mcp/tools.js.map +1 -1
- package/dist/reply.d.ts +11 -1
- package/dist/reply.d.ts.map +1 -1
- package/dist/reply.js +43 -0
- package/dist/reply.js.map +1 -1
- package/dist/search.d.ts +8 -1
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +36 -0
- package/dist/search.js.map +1 -1
- package/dist/searchCursor.d.ts +35 -0
- package/dist/searchCursor.d.ts.map +1 -0
- package/dist/searchCursor.js +113 -0
- package/dist/searchCursor.js.map +1 -0
- package/package.json +9 -1
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { createHash, createHmac, hkdfSync, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
import { EmailError } from './errors.js';
|
|
3
|
+
const CURSOR_VERSION = 1;
|
|
4
|
+
const CURSOR_LIFETIME_MS = 60 * 60 * 1_000;
|
|
5
|
+
const MAX_CURSOR_BYTES = 16 * 1_024;
|
|
6
|
+
const HKDF_CONTEXT = 'fluxmail/search-page-token/v1';
|
|
7
|
+
function canonicalQuery(query) {
|
|
8
|
+
const entries = Object.entries(query)
|
|
9
|
+
.filter(([, value]) => value !== undefined)
|
|
10
|
+
.sort(([left], [right]) => left.localeCompare(right));
|
|
11
|
+
return JSON.stringify(Object.fromEntries(entries));
|
|
12
|
+
}
|
|
13
|
+
export function emailQueryHash(query) {
|
|
14
|
+
return createHash('sha256').update(canonicalQuery(query)).digest('base64url');
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Node only, so it ships as `@fluxmail/core/search-cursor` instead of the root export.
|
|
18
|
+
*
|
|
19
|
+
* Wraps a provider's page token in a signed, expiring cursor bound to the account, query and
|
|
20
|
+
* page options, so a token can't be replayed against a different search.
|
|
21
|
+
*/
|
|
22
|
+
export class SearchCursorCodec {
|
|
23
|
+
key;
|
|
24
|
+
invalidCursor;
|
|
25
|
+
constructor(secret, options = {}) {
|
|
26
|
+
this.key = Buffer.from(hkdfSync('sha256', secret, Buffer.alloc(0), HKDF_CONTEXT, 32));
|
|
27
|
+
this.invalidCursor =
|
|
28
|
+
options.invalidCursor ?? (() => new EmailError('invalid_request', 'Invalid or expired search page token.'));
|
|
29
|
+
}
|
|
30
|
+
encode(binding, now = Date.now()) {
|
|
31
|
+
const payload = {
|
|
32
|
+
v: CURSOR_VERSION,
|
|
33
|
+
accountId: binding.accountId,
|
|
34
|
+
provider: binding.provider,
|
|
35
|
+
queryHash: emailQueryHash(binding.query),
|
|
36
|
+
pageSize: binding.pageSize,
|
|
37
|
+
...(binding.includeSnippet !== undefined ? { includeSnippet: binding.includeSnippet } : {}),
|
|
38
|
+
...(binding.includeSearchContext ? { includeSearchContext: true } : {}),
|
|
39
|
+
providerToken: binding.providerToken,
|
|
40
|
+
issuedAt: now,
|
|
41
|
+
expiresAt: now + CURSOR_LIFETIME_MS,
|
|
42
|
+
};
|
|
43
|
+
const encodedPayload = Buffer.from(JSON.stringify(payload)).toString('base64url');
|
|
44
|
+
const signature = createHmac('sha256', this.key).update(encodedPayload).digest('base64url');
|
|
45
|
+
const token = `${encodedPayload}.${signature}`;
|
|
46
|
+
if (Buffer.byteLength(token) > MAX_CURSOR_BYTES) {
|
|
47
|
+
throw new EmailError('invalid_request', 'The provider returned a search page token that is too large.');
|
|
48
|
+
}
|
|
49
|
+
return token;
|
|
50
|
+
}
|
|
51
|
+
decode(token, binding, now = Date.now()) {
|
|
52
|
+
if (Buffer.byteLength(token) > MAX_CURSOR_BYTES)
|
|
53
|
+
throw this.invalidCursor();
|
|
54
|
+
const parts = token.split('.');
|
|
55
|
+
if (parts.length !== 2 || !parts[0] || !parts[1])
|
|
56
|
+
throw this.invalidCursor();
|
|
57
|
+
const [encodedPayload, encodedSignature] = parts;
|
|
58
|
+
if (!/^[A-Za-z0-9_-]+$/.test(encodedPayload) || !/^[A-Za-z0-9_-]+$/.test(encodedSignature)) {
|
|
59
|
+
throw this.invalidCursor();
|
|
60
|
+
}
|
|
61
|
+
let suppliedSignature;
|
|
62
|
+
try {
|
|
63
|
+
suppliedSignature = Buffer.from(encodedSignature, 'base64url');
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
throw this.invalidCursor();
|
|
67
|
+
}
|
|
68
|
+
if (suppliedSignature.toString('base64url') !== encodedSignature)
|
|
69
|
+
throw this.invalidCursor();
|
|
70
|
+
const expectedSignature = createHmac('sha256', this.key).update(encodedPayload).digest();
|
|
71
|
+
if (suppliedSignature.length !== expectedSignature.length)
|
|
72
|
+
throw this.invalidCursor();
|
|
73
|
+
if (!timingSafeEqual(suppliedSignature, expectedSignature))
|
|
74
|
+
throw this.invalidCursor();
|
|
75
|
+
let payload;
|
|
76
|
+
try {
|
|
77
|
+
const bytes = Buffer.from(encodedPayload, 'base64url');
|
|
78
|
+
if (bytes.toString('base64url') !== encodedPayload)
|
|
79
|
+
throw new Error();
|
|
80
|
+
payload = JSON.parse(bytes.toString('utf8'));
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
throw this.invalidCursor();
|
|
84
|
+
}
|
|
85
|
+
if (!payload ||
|
|
86
|
+
payload.v !== CURSOR_VERSION ||
|
|
87
|
+
typeof payload.accountId !== 'string' ||
|
|
88
|
+
!['gmail', 'outlook', 'imap'].includes(payload.provider) ||
|
|
89
|
+
typeof payload.queryHash !== 'string' ||
|
|
90
|
+
!Number.isInteger(payload.pageSize) ||
|
|
91
|
+
(payload.includeSnippet !== undefined && typeof payload.includeSnippet !== 'boolean') ||
|
|
92
|
+
(payload.includeSearchContext !== undefined && typeof payload.includeSearchContext !== 'boolean') ||
|
|
93
|
+
typeof payload.providerToken !== 'string' ||
|
|
94
|
+
!payload.providerToken ||
|
|
95
|
+
!Number.isFinite(payload.issuedAt) ||
|
|
96
|
+
!Number.isFinite(payload.expiresAt) ||
|
|
97
|
+
payload.expiresAt !== payload.issuedAt + CURSOR_LIFETIME_MS ||
|
|
98
|
+
payload.issuedAt > now ||
|
|
99
|
+
payload.expiresAt <= now) {
|
|
100
|
+
throw this.invalidCursor();
|
|
101
|
+
}
|
|
102
|
+
if (payload.accountId !== binding.accountId ||
|
|
103
|
+
payload.provider !== binding.provider ||
|
|
104
|
+
payload.queryHash !== emailQueryHash(binding.query) ||
|
|
105
|
+
payload.pageSize !== binding.pageSize ||
|
|
106
|
+
payload.includeSnippet !== binding.includeSnippet ||
|
|
107
|
+
(payload.includeSearchContext ?? false) !== (binding.includeSearchContext ?? false)) {
|
|
108
|
+
throw this.invalidCursor();
|
|
109
|
+
}
|
|
110
|
+
return payload.providerToken;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=searchCursor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchCursor.js","sourceRoot":"","sources":["../src/searchCursor.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluxmail/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.1",
|
|
4
4
|
"description": "Unified email types and provider interface for Fluxmail",
|
|
5
5
|
"license": "Elastic-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -19,6 +19,14 @@
|
|
|
19
19
|
"./mcp": {
|
|
20
20
|
"types": "./dist/mcp/index.d.ts",
|
|
21
21
|
"default": "./dist/mcp/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./mcp/pdf": {
|
|
24
|
+
"types": "./dist/mcp/pdf.d.ts",
|
|
25
|
+
"default": "./dist/mcp/pdf.js"
|
|
26
|
+
},
|
|
27
|
+
"./search-cursor": {
|
|
28
|
+
"types": "./dist/searchCursor.d.ts",
|
|
29
|
+
"default": "./dist/searchCursor.js"
|
|
22
30
|
}
|
|
23
31
|
},
|
|
24
32
|
"files": [
|