@pome-sh/cli 0.7.0 → 0.8.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 (131) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/src/cli/docs-topics.js +5 -3
  3. package/dist/src/runner/runTask.d.ts +14 -0
  4. package/dist/src/task/taskSchema.d.ts +52 -16
  5. package/node_modules/@pome-sh/shared-types/dist/seed-state.d.ts +27 -0
  6. package/node_modules/@pome-sh/shared-types/dist/seed-state.js +12 -0
  7. package/node_modules/@pome-sh/shared-types/dist/seed-state.js.map +1 -1
  8. package/node_modules/@pome-sh/shared-types/dist/task.d.ts +18 -0
  9. package/node_modules/@pome-sh/shared-types/package.json +1 -1
  10. package/node_modules/@pome-sh/shared-types/trace-contract.json +1 -1
  11. package/node_modules/@pome-sh/twin-gmail/CHANGELOG.md +21 -0
  12. package/node_modules/@pome-sh/twin-gmail/HOSTED.md +37 -15
  13. package/node_modules/@pome-sh/twin-gmail/LIMITS.md +10 -0
  14. package/node_modules/@pome-sh/twin-gmail/README.md +52 -11
  15. package/node_modules/@pome-sh/twin-gmail/dist/fixtures/mcp-tools-list.canonical.json +242 -7
  16. package/node_modules/@pome-sh/twin-gmail/dist/src/db.js +6 -0
  17. package/node_modules/@pome-sh/twin-gmail/dist/src/db.js.map +1 -1
  18. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/drafts.d.ts +41 -0
  19. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/drafts.js +138 -0
  20. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/drafts.js.map +1 -0
  21. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/filters.d.ts +10 -0
  22. package/node_modules/@pome-sh/twin-gmail/dist/src/{domain-search.js → domain/filters.js} +52 -36
  23. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/filters.js.map +1 -0
  24. package/node_modules/@pome-sh/twin-gmail/dist/src/{domain.d.ts → domain/gmail-domain.d.ts} +45 -34
  25. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/gmail-domain.js +174 -0
  26. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/gmail-domain.js.map +1 -0
  27. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/hydrate.d.ts +8 -0
  28. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/hydrate.js +122 -0
  29. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/hydrate.js.map +1 -0
  30. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/index.d.ts +4 -0
  31. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/index.js +5 -0
  32. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/index.js.map +1 -0
  33. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/labels.d.ts +40 -0
  34. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/labels.js +122 -0
  35. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/labels.js.map +1 -0
  36. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/messages.d.ts +49 -0
  37. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/messages.js +276 -0
  38. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/messages.js.map +1 -0
  39. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/search-sql.d.ts +19 -0
  40. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/search-sql.js +179 -0
  41. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/search-sql.js.map +1 -0
  42. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/settings.d.ts +27 -0
  43. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/settings.js +98 -0
  44. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/settings.js.map +1 -0
  45. package/node_modules/@pome-sh/twin-gmail/dist/src/errors.js +2 -0
  46. package/node_modules/@pome-sh/twin-gmail/dist/src/errors.js.map +1 -1
  47. package/node_modules/@pome-sh/twin-gmail/dist/src/faults.d.ts +21 -0
  48. package/node_modules/@pome-sh/twin-gmail/dist/src/faults.js +52 -0
  49. package/node_modules/@pome-sh/twin-gmail/dist/src/faults.js.map +1 -0
  50. package/node_modules/@pome-sh/twin-gmail/dist/src/identity.d.ts +1 -6
  51. package/node_modules/@pome-sh/twin-gmail/dist/src/identity.js +0 -11
  52. package/node_modules/@pome-sh/twin-gmail/dist/src/identity.js.map +1 -1
  53. package/node_modules/@pome-sh/twin-gmail/dist/src/index.d.ts +4 -3
  54. package/node_modules/@pome-sh/twin-gmail/dist/src/index.js +3 -3
  55. package/node_modules/@pome-sh/twin-gmail/dist/src/index.js.map +1 -1
  56. package/node_modules/@pome-sh/twin-gmail/dist/src/mcp-schemas.d.ts +48 -0
  57. package/node_modules/@pome-sh/twin-gmail/dist/src/mcp-schemas.js +23 -0
  58. package/node_modules/@pome-sh/twin-gmail/dist/src/mcp-schemas.js.map +1 -1
  59. package/node_modules/@pome-sh/twin-gmail/dist/src/mcp.d.ts +1 -1
  60. package/node_modules/@pome-sh/twin-gmail/dist/src/mcp.js +39 -1
  61. package/node_modules/@pome-sh/twin-gmail/dist/src/mcp.js.map +1 -1
  62. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-drafts.js +4 -5
  63. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-drafts.js.map +1 -1
  64. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-kit.d.ts +2 -3
  65. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-kit.js +4 -4
  66. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-kit.js.map +1 -1
  67. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-messages.js +7 -8
  68. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-messages.js.map +1 -1
  69. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-resources.js +20 -21
  70. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-resources.js.map +1 -1
  71. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes.d.ts +1 -1
  72. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-serializers.d.ts +2 -4
  73. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-serializers.js +4 -6
  74. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-serializers.js.map +1 -1
  75. package/node_modules/@pome-sh/twin-gmail/dist/src/search-match.d.ts +4 -0
  76. package/node_modules/@pome-sh/twin-gmail/dist/src/search-match.js +179 -0
  77. package/node_modules/@pome-sh/twin-gmail/dist/src/search-match.js.map +1 -0
  78. package/node_modules/@pome-sh/twin-gmail/dist/src/search-parse.d.ts +61 -0
  79. package/node_modules/@pome-sh/twin-gmail/dist/src/search-parse.js +318 -0
  80. package/node_modules/@pome-sh/twin-gmail/dist/src/search-parse.js.map +1 -0
  81. package/node_modules/@pome-sh/twin-gmail/dist/src/search.d.ts +3 -61
  82. package/node_modules/@pome-sh/twin-gmail/dist/src/search.js +2 -503
  83. package/node_modules/@pome-sh/twin-gmail/dist/src/search.js.map +1 -1
  84. package/node_modules/@pome-sh/twin-gmail/dist/src/seed.d.ts +13 -4
  85. package/node_modules/@pome-sh/twin-gmail/dist/src/seed.js +3 -1
  86. package/node_modules/@pome-sh/twin-gmail/dist/src/seed.js.map +1 -1
  87. package/node_modules/@pome-sh/twin-gmail/dist/src/server.js +1 -1
  88. package/node_modules/@pome-sh/twin-gmail/dist/src/server.js.map +1 -1
  89. package/node_modules/@pome-sh/twin-gmail/dist/src/storage.js +1 -1
  90. package/node_modules/@pome-sh/twin-gmail/dist/src/storage.js.map +1 -1
  91. package/node_modules/@pome-sh/twin-gmail/dist/src/twin.d.ts +2 -3
  92. package/node_modules/@pome-sh/twin-gmail/dist/src/twin.js +1 -4
  93. package/node_modules/@pome-sh/twin-gmail/dist/src/twin.js.map +1 -1
  94. package/node_modules/@pome-sh/twin-gmail/dist/src/types.d.ts +1 -0
  95. package/node_modules/@pome-sh/twin-gmail/fidelity.inventory.json +42 -435
  96. package/node_modules/@pome-sh/twin-gmail/fixtures/README.md +4 -4
  97. package/node_modules/@pome-sh/twin-gmail/fixtures/mcp-tools-list.canonical.json +242 -7
  98. package/node_modules/@pome-sh/twin-gmail/fixtures/mcp-tools-list.meta.json +3 -3
  99. package/node_modules/@pome-sh/twin-gmail/package.json +3 -2
  100. package/node_modules/hono/dist/cjs/client/utils.js +1 -1
  101. package/node_modules/hono/dist/cjs/helper/streaming/sse.js +5 -4
  102. package/node_modules/hono/dist/cjs/middleware/cache/index.js +1 -1
  103. package/node_modules/hono/dist/cjs/middleware/compress/index.js +2 -1
  104. package/node_modules/hono/dist/cjs/middleware/method-override/index.js +5 -3
  105. package/node_modules/hono/dist/cjs/middleware/secure-headers/secure-headers.js +10 -4
  106. package/node_modules/hono/dist/cjs/request.js +8 -3
  107. package/node_modules/hono/dist/cjs/utils/accept.js +1 -1
  108. package/node_modules/hono/dist/cjs/utils/body.js +6 -0
  109. package/node_modules/hono/dist/cjs/utils/url.js +1 -1
  110. package/node_modules/hono/dist/client/utils.js +1 -1
  111. package/node_modules/hono/dist/helper/streaming/sse.js +5 -4
  112. package/node_modules/hono/dist/middleware/cache/index.js +1 -1
  113. package/node_modules/hono/dist/middleware/compress/index.js +2 -1
  114. package/node_modules/hono/dist/middleware/method-override/index.js +5 -3
  115. package/node_modules/hono/dist/middleware/secure-headers/secure-headers.js +10 -4
  116. package/node_modules/hono/dist/request.js +8 -3
  117. package/node_modules/hono/dist/types/adapter/aws-lambda/types.d.ts +9 -0
  118. package/node_modules/hono/dist/types/helper/websocket/index.d.ts +1 -1
  119. package/node_modules/hono/dist/types/middleware/combine/index.d.ts +1 -1
  120. package/node_modules/hono/dist/utils/accept.js +1 -1
  121. package/node_modules/hono/dist/utils/body.js +6 -0
  122. package/node_modules/hono/dist/utils/url.js +1 -1
  123. package/node_modules/hono/package.json +3 -3
  124. package/package.json +3 -3
  125. package/node_modules/@pome-sh/twin-gmail/dist/src/domain-search.d.ts +0 -5
  126. package/node_modules/@pome-sh/twin-gmail/dist/src/domain-search.js.map +0 -1
  127. package/node_modules/@pome-sh/twin-gmail/dist/src/domain.js +0 -407
  128. package/node_modules/@pome-sh/twin-gmail/dist/src/domain.js.map +0 -1
  129. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-store.d.ts +0 -75
  130. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-store.js +0 -282
  131. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-store.js.map +0 -1
@@ -1,11 +1,9 @@
1
- import type { GmailDomain } from "./domain.js";
1
+ import type { GmailDomain, LabelResource } from "./domain/index.js";
2
2
  import type { MessageFormat } from "./rest-common.js";
3
- import type { GmailRestStore, LabelResource } from "./rest-store.js";
4
3
  import type { HistoryEvent, SemanticMessage } from "./types.js";
5
4
  export declare class GmailRestSerializers {
6
5
  private readonly domain;
7
- private readonly store;
8
- constructor(domain: GmailDomain, store: GmailRestStore);
6
+ constructor(domain: GmailDomain);
9
7
  message(email: string, message: SemanticMessage, format?: MessageFormat, metadataHeaders?: string[]): Record<string, unknown>;
10
8
  thread(email: string, thread: ReturnType<GmailDomain["getThread"]>, format?: Exclude<MessageFormat, "raw">, metadataHeaders?: string[]): Record<string, unknown>;
11
9
  draft(email: string, draft: {
@@ -1,10 +1,8 @@
1
1
  import { encodeGmailRaw } from "./mime.js";
2
2
  export class GmailRestSerializers {
3
3
  domain;
4
- store;
5
- constructor(domain, store) {
4
+ constructor(domain) {
6
5
  this.domain = domain;
7
- this.store = store;
8
6
  }
9
7
  message(email, message, format = "full", metadataHeaders = []) {
10
8
  const base = {
@@ -12,7 +10,7 @@ export class GmailRestSerializers {
12
10
  threadId: message.threadId,
13
11
  labelIds: message.labelIds,
14
12
  snippet: message.snippet,
15
- historyId: this.store.latestMessageHistory(email, message.id),
13
+ historyId: this.domain.latestMessageHistory(email, message.id),
16
14
  internalDate: String(message.internalDate),
17
15
  sizeEstimate: message.sizeEstimate,
18
16
  };
@@ -21,7 +19,7 @@ export class GmailRestSerializers {
21
19
  if (format === "raw") {
22
20
  return { ...base, raw: encodeGmailRaw(this.domain.getRaw(email, message.id)) };
23
21
  }
24
- const headers = this.store.headers(email, message.id);
22
+ const headers = this.domain.headers(email, message.id);
25
23
  if (format === "metadata") {
26
24
  return {
27
25
  ...base,
@@ -40,7 +38,7 @@ export class GmailRestSerializers {
40
38
  const latest = thread.messages.at(-1);
41
39
  return {
42
40
  id: thread.id,
43
- historyId: this.store.latestThreadHistory(email, thread.id),
41
+ historyId: this.domain.latestThreadHistory(email, thread.id),
44
42
  ...(latest?.snippet ? { snippet: latest.snippet } : {}),
45
43
  messages: thread.messages.map((message) => this.message(email, message, format, metadataHeaders)),
46
44
  };
@@ -1 +1 @@
1
- {"version":3,"file":"rest-serializers.js","sourceRoot":"","sources":["../../src/rest-serializers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rest-serializers.js","sourceRoot":"","sources":["../../src/rest-serializers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { type SearchDocument, type SearchNode } from "./search-parse.js";
2
+ export declare function matchesSearch(node: SearchNode, document: SearchDocument, nowMs?: number): boolean;
3
+ /** Linear HTML tag strip — safe for untrusted MIME (no ReDoS). */
4
+ export declare function stripHtmlTags(value: string): string;
@@ -0,0 +1,179 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { invalidArgument } from "./errors.js";
3
+ import { assertHasOperator, CATEGORY_LABELS, KNOWN_FIELDS, parseDate, parseDuration, parseSize, } from "./search-parse.js";
4
+ export function matchesSearch(node, document, nowMs = Date.now()) {
5
+ switch (node.type) {
6
+ case "and":
7
+ return node.children.every((child) => matchesSearch(child, document, nowMs));
8
+ case "or":
9
+ return node.children.some((child) => matchesSearch(child, document, nowMs));
10
+ case "not":
11
+ return !matchesSearch(node.child, document, nowMs);
12
+ case "around":
13
+ return matchesAround(searchable(document), node.left, node.right, node.distance);
14
+ case "term":
15
+ return matchesTerm(node.field, node.value, node.exact === true, document, nowMs);
16
+ }
17
+ }
18
+ function matchesTerm(field, rawValue, exact, document, nowMs) {
19
+ const value = rawValue.toLocaleLowerCase("en-US");
20
+ const contains = (candidate) => matchText(candidate, value, exact);
21
+ if (!field)
22
+ return contains(searchable(document));
23
+ if (!KNOWN_FIELDS.has(field)) {
24
+ invalidArgument(`Unsupported search operator: ${field}`);
25
+ }
26
+ if (field === "from")
27
+ return contains(document.from);
28
+ if (field === "to")
29
+ return document.to.some(contains);
30
+ if (field === "cc")
31
+ return document.cc.some(contains);
32
+ if (field === "bcc")
33
+ return document.bcc.some(contains);
34
+ if (field === "deliveredto")
35
+ return contains(document.deliveredTo);
36
+ if (field === "list") {
37
+ return document.headers.some((header) => header.name.toLowerCase() === "list-id" && contains(header.value));
38
+ }
39
+ if (field === "subject")
40
+ return contains(document.subject);
41
+ if (field === "rfc822msgid")
42
+ return normalizeMessageId(document.rfcMessageId) === normalizeMessageId(value);
43
+ if (field === "filename") {
44
+ return document.attachmentNames.some(contains) || document.attachmentMimeTypes.some(contains);
45
+ }
46
+ if (field === "after" || field === "newer")
47
+ return document.dateMs > parseDate(value);
48
+ if (field === "before" || field === "older")
49
+ return document.dateMs < parseDate(value);
50
+ if (field === "newer_than")
51
+ return document.dateMs > nowMs - parseDuration(value);
52
+ if (field === "older_than")
53
+ return document.dateMs < nowMs - parseDuration(value);
54
+ if (field === "size")
55
+ return document.size === parseSize(value);
56
+ if (field === "larger")
57
+ return document.size > parseSize(value);
58
+ if (field === "smaller")
59
+ return document.size < parseSize(value);
60
+ if (field === "label")
61
+ return hasLabel(document, value);
62
+ if (field === "category")
63
+ return matchesCategory(value, document);
64
+ if (field === "in")
65
+ return matchesFolder(value, document);
66
+ if (field === "is")
67
+ return matchesStatus(value, document);
68
+ if (field === "has")
69
+ return matchesHas(value, document);
70
+ invalidArgument(`Unsupported search operator: ${field}`);
71
+ }
72
+ function matchesCategory(value, document) {
73
+ const mapped = CATEGORY_LABELS[value.toLocaleLowerCase("en-US")];
74
+ if (!mapped)
75
+ invalidArgument(`Unsupported search category: ${value}`);
76
+ return hasLabel(document, mapped);
77
+ }
78
+ function matchesFolder(value, document) {
79
+ if (value === "anywhere")
80
+ return true;
81
+ if (value === "archive")
82
+ return !hasLabel(document, "inbox");
83
+ if (value === "draft")
84
+ return hasLabel(document, "draft");
85
+ return hasLabel(document, value);
86
+ }
87
+ function matchesStatus(value, document) {
88
+ if (value === "read")
89
+ return !hasLabel(document, "unread");
90
+ if (value === "unread")
91
+ return hasLabel(document, "unread");
92
+ if (value === "starred")
93
+ return hasLabel(document, "starred");
94
+ if (value === "important")
95
+ return hasLabel(document, "important");
96
+ if (value === "muted")
97
+ return hasLabel(document, "muted");
98
+ return hasLabel(document, value);
99
+ }
100
+ function matchesHas(value, document) {
101
+ const normalized = value.toLocaleLowerCase("en-US");
102
+ assertHasOperator(normalized);
103
+ if (normalized === "attachment")
104
+ return document.attachmentNames.length > 0;
105
+ if (normalized === "userlabels")
106
+ return document.userLabelCount > 0;
107
+ if (normalized === "nouserlabels")
108
+ return document.userLabelCount === 0;
109
+ if (normalized === "youtube")
110
+ return /youtube\.com|youtu\.be/i.test(searchable(document));
111
+ if (["drive", "document"].includes(normalized)) {
112
+ return /drive\.google\.com|docs\.google\.com/i.test(searchable(document));
113
+ }
114
+ return false;
115
+ }
116
+ function hasLabel(document, value) {
117
+ const normalized = value.toLocaleLowerCase("en-US");
118
+ return document.labels.some((label) => label.toLocaleLowerCase("en-US") === normalized);
119
+ }
120
+ function searchable(document) {
121
+ // Strip tags with a linear scan — avoid backtracking regex on hostile HTML.
122
+ const htmlText = stripHtmlTags(document.html);
123
+ return [
124
+ document.from,
125
+ ...document.to,
126
+ ...document.cc,
127
+ ...document.bcc,
128
+ document.subject,
129
+ document.text,
130
+ htmlText,
131
+ ...document.attachmentNames,
132
+ ].join(" ");
133
+ }
134
+ /** Linear HTML tag strip — safe for untrusted MIME (no ReDoS). */
135
+ export function stripHtmlTags(value) {
136
+ let out = "";
137
+ let inTag = false;
138
+ for (let index = 0; index < value.length; index += 1) {
139
+ const char = value[index];
140
+ if (char === "<") {
141
+ inTag = true;
142
+ continue;
143
+ }
144
+ if (char === ">" && inTag) {
145
+ inTag = false;
146
+ out += " ";
147
+ continue;
148
+ }
149
+ if (!inTag)
150
+ out += char;
151
+ }
152
+ return out;
153
+ }
154
+ function matchText(candidate, value, exact) {
155
+ const haystack = candidate.toLocaleLowerCase("en-US");
156
+ if (!exact)
157
+ return haystack.includes(value);
158
+ const pattern = new RegExp(`(?:^|[^\\p{L}\\p{N}])${escapeRegExp(value)}(?:$|[^\\p{L}\\p{N}])`, "iu");
159
+ return value.includes(" ") ? haystack.includes(value) : pattern.test(haystack);
160
+ }
161
+ function matchesAround(text, left, right, distance) {
162
+ const words = text.toLocaleLowerCase("en-US").split(/[^\p{L}\p{N}@._+-]+/u);
163
+ const leftValue = left.toLocaleLowerCase("en-US");
164
+ const rightValue = right.toLocaleLowerCase("en-US");
165
+ const leftIndexes = words.flatMap((word, index) => (word === leftValue ? [index] : []));
166
+ return leftIndexes.some((index) => words.slice(Math.max(0, index - distance), index + distance + 1).includes(rightValue));
167
+ }
168
+ function normalizeMessageId(value) {
169
+ let normalized = value.trim();
170
+ if (normalized.startsWith("<"))
171
+ normalized = normalized.slice(1);
172
+ if (normalized.endsWith(">"))
173
+ normalized = normalized.slice(0, -1);
174
+ return normalized.toLowerCase();
175
+ }
176
+ function escapeRegExp(value) {
177
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
178
+ }
179
+ //# sourceMappingURL=search-match.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-match.js","sourceRoot":"","sources":["../../src/search-match.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ export type SearchNode = {
2
+ type: "and";
3
+ children: SearchNode[];
4
+ } | {
5
+ type: "or";
6
+ children: SearchNode[];
7
+ } | {
8
+ type: "not";
9
+ child: SearchNode;
10
+ } | {
11
+ type: "term";
12
+ field?: string;
13
+ value: string;
14
+ exact?: boolean;
15
+ } | {
16
+ type: "around";
17
+ left: string;
18
+ right: string;
19
+ distance: number;
20
+ };
21
+ export type SearchDocument = {
22
+ from: string;
23
+ to: string[];
24
+ cc: string[];
25
+ bcc: string[];
26
+ deliveredTo: string;
27
+ subject: string;
28
+ text: string;
29
+ html: string;
30
+ dateMs: number;
31
+ rfcMessageId: string;
32
+ size: number;
33
+ labels: string[];
34
+ userLabelCount: number;
35
+ attachmentNames: string[];
36
+ attachmentMimeTypes: string[];
37
+ headers: Array<{
38
+ name: string;
39
+ value: string;
40
+ }>;
41
+ };
42
+ /**
43
+ * Hard mailbox-size budget for the intentional in-memory search evaluator.
44
+ * Search hydrates semantic rows in process; exceeding this fails loudly before OOM.
45
+ */
46
+ export declare const SEARCH_MAILBOX_MESSAGE_BUDGET = 10000;
47
+ /** Operators supported by the twin search grammar (unknowns are rejected). */
48
+ export declare const KNOWN_FIELDS: Set<string>;
49
+ /** Gmail `category:` aliases → system label ids. */
50
+ export declare const CATEGORY_LABELS: Record<string, string>;
51
+ /**
52
+ * Parse a Gmail query and reject operators/values that would throw at match time
53
+ * (unknown fields, categories, and invalid date/size/duration literals).
54
+ */
55
+ export declare function validateSearchQuery(query: string): SearchNode;
56
+ export declare function assertSearchTerm(field: string | undefined, value: string): void;
57
+ export declare function parseSearchQuery(query: string): SearchNode;
58
+ export declare function assertHasOperator(value: string): void;
59
+ export declare function parseDate(value: string): number;
60
+ export declare function parseDuration(value: string): number;
61
+ export declare function parseSize(value: string): number;
@@ -0,0 +1,318 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { invalidArgument } from "./errors.js";
3
+ const MAX_QUERY_BYTES = 4096;
4
+ const MAX_TOKENS = 256;
5
+ const MAX_DEPTH = 20;
6
+ const MAX_BRANCHES = 256;
7
+ /**
8
+ * Hard mailbox-size budget for the intentional in-memory search evaluator.
9
+ * Search hydrates semantic rows in process; exceeding this fails loudly before OOM.
10
+ */
11
+ export const SEARCH_MAILBOX_MESSAGE_BUDGET = 10_000;
12
+ /** Operators supported by the twin search grammar (unknowns are rejected). */
13
+ export const KNOWN_FIELDS = new Set([
14
+ "from",
15
+ "to",
16
+ "cc",
17
+ "bcc",
18
+ "deliveredto",
19
+ "list",
20
+ "subject",
21
+ "rfc822msgid",
22
+ "filename",
23
+ "after",
24
+ "newer",
25
+ "before",
26
+ "older",
27
+ "newer_than",
28
+ "older_than",
29
+ "size",
30
+ "larger",
31
+ "smaller",
32
+ "label",
33
+ "category",
34
+ "in",
35
+ "is",
36
+ "has",
37
+ ]);
38
+ /** Gmail `category:` aliases → system label ids. */
39
+ export const CATEGORY_LABELS = {
40
+ primary: "CATEGORY_PERSONAL",
41
+ personal: "CATEGORY_PERSONAL",
42
+ social: "CATEGORY_SOCIAL",
43
+ promotions: "CATEGORY_PROMOTIONS",
44
+ updates: "CATEGORY_UPDATES",
45
+ forums: "CATEGORY_FORUMS",
46
+ };
47
+ /**
48
+ * Parse a Gmail query and reject operators/values that would throw at match time
49
+ * (unknown fields, categories, and invalid date/size/duration literals).
50
+ */
51
+ export function validateSearchQuery(query) {
52
+ const node = parseSearchQuery(query);
53
+ const walk = (current) => {
54
+ switch (current.type) {
55
+ case "and":
56
+ case "or":
57
+ for (const child of current.children)
58
+ walk(child);
59
+ return;
60
+ case "not":
61
+ walk(current.child);
62
+ return;
63
+ case "around":
64
+ return;
65
+ case "term":
66
+ assertSearchTerm(current.field, current.value);
67
+ return;
68
+ }
69
+ };
70
+ walk(node);
71
+ return node;
72
+ }
73
+ export function assertSearchTerm(field, value) {
74
+ if (!field)
75
+ return;
76
+ if (!KNOWN_FIELDS.has(field)) {
77
+ invalidArgument(`Unsupported search operator: ${field}`);
78
+ }
79
+ if (field === "category") {
80
+ if (!CATEGORY_LABELS[value.toLocaleLowerCase("en-US")]) {
81
+ invalidArgument(`Unsupported search category: ${value}`);
82
+ }
83
+ return;
84
+ }
85
+ if (field === "after" || field === "newer" || field === "before" || field === "older") {
86
+ parseDate(value);
87
+ return;
88
+ }
89
+ if (field === "newer_than" || field === "older_than") {
90
+ parseDuration(value);
91
+ return;
92
+ }
93
+ if (field === "size" || field === "larger" || field === "smaller") {
94
+ parseSize(value);
95
+ return;
96
+ }
97
+ if (field === "has") {
98
+ assertHasOperator(value);
99
+ }
100
+ }
101
+ export function parseSearchQuery(query) {
102
+ if (Buffer.byteLength(query) > MAX_QUERY_BYTES)
103
+ invalidArgument("Search query exceeds limit");
104
+ const tokens = tokenize(query);
105
+ if (tokens.length > MAX_TOKENS)
106
+ invalidArgument("Search query has too many tokens");
107
+ if (tokens.length === 0)
108
+ return { type: "and", children: [] };
109
+ let position = 0;
110
+ const parseExpression = (depth, stop) => {
111
+ if (depth > MAX_DEPTH)
112
+ invalidArgument("Search query nesting exceeds limit");
113
+ const alternatives = [];
114
+ let conjunction = [];
115
+ const flush = () => {
116
+ alternatives.push(conjunction.length === 1 ? conjunction[0] : { type: "and", children: conjunction });
117
+ conjunction = [];
118
+ };
119
+ while (position < tokens.length) {
120
+ const token = tokens[position];
121
+ if (stop && token.value === stop)
122
+ break;
123
+ if (token.value.toUpperCase() === "OR") {
124
+ position++;
125
+ if (!conjunction.length)
126
+ invalidArgument("OR requires a left expression");
127
+ flush();
128
+ continue;
129
+ }
130
+ if (token.value.toUpperCase() === "AND") {
131
+ position++;
132
+ continue;
133
+ }
134
+ conjunction.push(parsePrimary(depth + 1));
135
+ }
136
+ if (conjunction.length)
137
+ flush();
138
+ if (!alternatives.length)
139
+ return { type: "and", children: [] };
140
+ return alternatives.length === 1 ? alternatives[0] : { type: "or", children: alternatives };
141
+ };
142
+ const parsePrimary = (depth) => {
143
+ const token = tokens[position++];
144
+ if (token.value === "(" || token.value === "{") {
145
+ const end = token.value === "(" ? ")" : "}";
146
+ const child = parseExpression(depth, end);
147
+ if (tokens[position]?.value !== end)
148
+ invalidArgument(`Unclosed ${token.value}`);
149
+ position++;
150
+ return token.value === "{" ? makeImplicitOr(child) : child;
151
+ }
152
+ if (token.value === ")" || token.value === "}")
153
+ invalidArgument(`Unexpected ${token.value}`);
154
+ let value = token.value;
155
+ let negate = false;
156
+ if (value === "-") {
157
+ negate = true;
158
+ const next = tokens[position++];
159
+ if (!next)
160
+ invalidArgument("Negation requires an expression");
161
+ position--;
162
+ const child = parsePrimary(depth + 1);
163
+ return { type: "not", child };
164
+ }
165
+ if (value.startsWith("-") && value.length > 1) {
166
+ negate = true;
167
+ value = value.slice(1);
168
+ }
169
+ const around = tokens[position]?.value.toUpperCase() === "AROUND";
170
+ if (around) {
171
+ position++;
172
+ const distance = Number(tokens[position++]?.value);
173
+ const right = tokens[position++]?.value;
174
+ if (!Number.isInteger(distance) || distance < 1 || distance > 100 || !right) {
175
+ invalidArgument("AROUND requires a distance and right term");
176
+ }
177
+ const node = { type: "around", left: value, right, distance };
178
+ return negate ? { type: "not", child: node } : node;
179
+ }
180
+ const colon = value.indexOf(":");
181
+ let node;
182
+ if (colon > 0) {
183
+ const field = value.slice(0, colon).toLowerCase();
184
+ let fieldValue = value.slice(colon + 1);
185
+ if (!fieldValue && (tokens[position]?.value === "(" || tokens[position]?.value === "{")) {
186
+ node = parseFieldGroup(field, depth + 1);
187
+ return negate ? { type: "not", child: node } : node;
188
+ }
189
+ if (!fieldValue && tokens[position] && !["AND", "OR", ")", "}"].includes(tokens[position].value.toUpperCase())) {
190
+ fieldValue = tokens[position++].value;
191
+ }
192
+ node = { type: "term", field, value: fieldValue, exact: token.quoted };
193
+ }
194
+ else {
195
+ node = { type: "term", value: value.startsWith("+") ? value.slice(1) : value, exact: token.quoted || value.startsWith("+") };
196
+ }
197
+ return negate ? { type: "not", child: node } : node;
198
+ };
199
+ const parseFieldGroup = (field, depth) => {
200
+ if (depth > MAX_DEPTH)
201
+ invalidArgument("Search query nesting exceeds limit");
202
+ const opening = tokens[position++].value;
203
+ const end = opening === "(" ? ")" : "}";
204
+ const groups = [[]];
205
+ while (position < tokens.length && tokens[position].value !== end) {
206
+ const token = tokens[position++];
207
+ if (token.value.toUpperCase() === "OR") {
208
+ groups.push([]);
209
+ continue;
210
+ }
211
+ if (token.value.toUpperCase() === "AND")
212
+ continue;
213
+ if (["(", "{", ")", "}"].includes(token.value))
214
+ invalidArgument("Nested field groups are unsupported");
215
+ let value = token.value;
216
+ let negate = false;
217
+ if (value.startsWith("-")) {
218
+ negate = true;
219
+ value = value.slice(1);
220
+ }
221
+ const term = { type: "term", field, value, exact: token.quoted };
222
+ groups.at(-1).push(negate ? { type: "not", child: term } : term);
223
+ }
224
+ if (tokens[position]?.value !== end)
225
+ invalidArgument(`Unclosed ${opening}`);
226
+ position++;
227
+ const nodes = groups.map((children) => children.length === 1 ? children[0] : { type: "and", children });
228
+ const useOr = opening === "{" || nodes.length > 1;
229
+ return useOr ? { type: "or", children: nodes } : nodes[0] ?? { type: "and", children: [] };
230
+ };
231
+ const root = parseExpression(0);
232
+ if (position !== tokens.length)
233
+ invalidArgument("Unexpected search token");
234
+ if (countBranches(root) > MAX_BRANCHES)
235
+ invalidArgument("Search query has too many branches");
236
+ return root;
237
+ }
238
+ export function assertHasOperator(value) {
239
+ const normalized = value.toLocaleLowerCase("en-US");
240
+ if (normalized.endsWith("-star")) {
241
+ invalidArgument(`Unsupported colored-star operator: has:${value}; twin maps only STARRED via is:starred`);
242
+ }
243
+ }
244
+ export function parseDate(value) {
245
+ const normalized = /^\d{4}\/\d{1,2}\/\d{1,2}$/.test(value) ? value.replaceAll("/", "-") : value;
246
+ const date = Date.parse(`${normalized}${/^\d{4}-\d/.test(normalized) ? "T00:00:00Z" : ""}`);
247
+ if (Number.isNaN(date))
248
+ invalidArgument(`Invalid search date: ${value}`);
249
+ return date;
250
+ }
251
+ export function parseDuration(value) {
252
+ const match = value.match(/^(\d+)([dmy])$/i);
253
+ if (!match)
254
+ invalidArgument(`Invalid search duration: ${value}`);
255
+ const units = { d: 86_400_000, m: 30 * 86_400_000, y: 365 * 86_400_000 };
256
+ return Number(match[1]) * units[match[2].toLowerCase()];
257
+ }
258
+ export function parseSize(value) {
259
+ const match = value.match(/^(\d+(?:\.\d+)?)([kmg])?$/i);
260
+ if (!match)
261
+ invalidArgument(`Invalid search size: ${value}`);
262
+ const scale = { k: 1024, m: 1024 ** 2, g: 1024 ** 3 };
263
+ return Math.floor(Number(match[1]) * (match[2] ? scale[match[2].toLowerCase()] : 1));
264
+ }
265
+ function countBranches(node) {
266
+ switch (node.type) {
267
+ case "and":
268
+ case "or":
269
+ return node.children.reduce((sum, child) => sum + countBranches(child), 0);
270
+ case "not":
271
+ return countBranches(node.child);
272
+ case "around":
273
+ case "term":
274
+ return 1;
275
+ }
276
+ }
277
+ function tokenize(query) {
278
+ const out = [];
279
+ let index = 0;
280
+ while (index < query.length) {
281
+ if (/\s/.test(query[index])) {
282
+ index++;
283
+ continue;
284
+ }
285
+ const char = query[index];
286
+ if ("(){}".includes(char)) {
287
+ out.push({ value: char });
288
+ index++;
289
+ continue;
290
+ }
291
+ let value = "";
292
+ let quoted = false;
293
+ while (index < query.length && !/\s/.test(query[index]) && !"(){}".includes(query[index])) {
294
+ if (query[index] === '"') {
295
+ quoted = true;
296
+ index++;
297
+ while (index < query.length && query[index] !== '"') {
298
+ if (query[index] === "\\" && index + 1 < query.length)
299
+ index++;
300
+ value += query[index++];
301
+ }
302
+ if (query[index] !== '"')
303
+ invalidArgument("Unclosed search quote");
304
+ index++;
305
+ }
306
+ else {
307
+ value += query[index++];
308
+ }
309
+ }
310
+ if (value)
311
+ out.push({ value, quoted });
312
+ }
313
+ return out;
314
+ }
315
+ function makeImplicitOr(node) {
316
+ return node.type === "and" ? { type: "or", children: node.children } : node;
317
+ }
318
+ //# sourceMappingURL=search-parse.js.map