@1kbirds/chidori-mock-gmail 0.1.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 (49) hide show
  1. package/README.md +85 -0
  2. package/dist/api.d.ts +14 -0
  3. package/dist/api.d.ts.map +1 -0
  4. package/dist/api.js +139 -0
  5. package/dist/client.d.ts +228 -0
  6. package/dist/client.d.ts.map +1 -0
  7. package/dist/client.js +50 -0
  8. package/dist/errors.d.ts +19 -0
  9. package/dist/errors.d.ts.map +1 -0
  10. package/dist/errors.js +25 -0
  11. package/dist/index.d.ts +10 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +9 -0
  14. package/dist/seed.d.ts +6 -0
  15. package/dist/seed.d.ts.map +1 -0
  16. package/dist/seed.js +127 -0
  17. package/dist/service.d.ts +41 -0
  18. package/dist/service.d.ts.map +1 -0
  19. package/dist/service.js +372 -0
  20. package/dist/state.d.ts +22 -0
  21. package/dist/state.d.ts.map +1 -0
  22. package/dist/state.js +139 -0
  23. package/dist/types.d.ts +123 -0
  24. package/dist/types.d.ts.map +1 -0
  25. package/dist/types.js +1 -0
  26. package/dist/ui/GmailMockApp.d.ts +7 -0
  27. package/dist/ui/GmailMockApp.d.ts.map +1 -0
  28. package/dist/ui/GmailMockApp.js +93 -0
  29. package/dist/ui/dev.d.ts +2 -0
  30. package/dist/ui/dev.d.ts.map +1 -0
  31. package/dist/ui/dev.js +11 -0
  32. package/dist/ui/index.d.ts +3 -0
  33. package/dist/ui/index.d.ts.map +1 -0
  34. package/dist/ui/index.js +1 -0
  35. package/dist/ui/styles.css +340 -0
  36. package/package.json +56 -0
  37. package/src/__tests__/service.test.ts +120 -0
  38. package/src/api.ts +157 -0
  39. package/src/client.ts +54 -0
  40. package/src/errors.ts +29 -0
  41. package/src/index.ts +12 -0
  42. package/src/seed.ts +143 -0
  43. package/src/service.ts +405 -0
  44. package/src/state.ts +159 -0
  45. package/src/types.ts +149 -0
  46. package/src/ui/GmailMockApp.tsx +236 -0
  47. package/src/ui/dev.tsx +16 -0
  48. package/src/ui/index.ts +2 -0
  49. package/src/ui/styles.css +340 -0
package/README.md ADDED
@@ -0,0 +1,85 @@
1
+ # @1kbirds/chidori-mock-gmail
2
+
3
+ In-memory Gmail mock for agent testing. The package provides:
4
+
5
+ - A deterministic in-memory mailbox service.
6
+ - A googleapis-like Gmail client facade.
7
+ - A REST-style Gmail API adapter.
8
+ - A React Gmail review UI.
9
+ - Seed data for inbox, sent mail, drafts, attachments, labels, and threads.
10
+
11
+ ## Supported Surface
12
+
13
+ SDK-style methods:
14
+
15
+ - `users.getProfile`
16
+ - `users.labels.list/get/create/update/delete`
17
+ - `users.messages.list/get/insert/send/modify/trash/untrash/delete`
18
+ - `users.threads.list/get/modify/trash`
19
+ - `users.drafts.list/get/create/update/send/delete`
20
+
21
+ REST-style paths:
22
+
23
+ - `GET /gmail/v1/users/me/profile`
24
+ - `GET|POST /gmail/v1/users/me/labels`
25
+ - `GET|PUT|PATCH|DELETE /gmail/v1/users/me/labels/:id`
26
+ - `GET|POST /gmail/v1/users/me/messages`
27
+ - `POST /gmail/v1/users/me/messages/send`
28
+ - `GET|DELETE /gmail/v1/users/me/messages/:id`
29
+ - `POST /gmail/v1/users/me/messages/:id/modify`
30
+ - `POST /gmail/v1/users/me/messages/:id/trash`
31
+ - `POST /gmail/v1/users/me/messages/:id/untrash`
32
+ - `GET /gmail/v1/users/me/threads`
33
+ - `GET /gmail/v1/users/me/threads/:id`
34
+ - `POST /gmail/v1/users/me/threads/:id/modify`
35
+ - `POST /gmail/v1/users/me/threads/:id/trash`
36
+ - `GET|POST /gmail/v1/users/me/drafts`
37
+ - `GET|PUT|DELETE /gmail/v1/users/me/drafts/:id`
38
+ - `POST /gmail/v1/users/me/drafts/:id/send`
39
+
40
+ ## Search Support
41
+
42
+ The first implementation supports common query terms:
43
+
44
+ - Plain text across headers, snippet, and body.
45
+ - `from:email`
46
+ - `to:email`
47
+ - `subject:text`
48
+ - `label:LABEL_ID`
49
+ - `is:unread`
50
+ - `is:read`
51
+ - `in:inbox`
52
+ - `in:sent`
53
+ - `in:trash`
54
+
55
+ ## Review
56
+
57
+ Run verification:
58
+
59
+ ```sh
60
+ npm run build
61
+ npm test
62
+ ```
63
+
64
+ Start the React review app:
65
+
66
+ ```sh
67
+ npm run dev:gmail
68
+ ```
69
+
70
+ Then open `http://127.0.0.1:5175/`.
71
+
72
+ Manual review should confirm:
73
+
74
+ - Seeded inbox, sent messages, drafts, trash, labels, threads, and attachments render.
75
+ - Search filters visible messages.
76
+ - Reading unread mail clears `UNREAD`.
77
+ - Compose can save a draft or send a message.
78
+ - Drafts can be edited and sent.
79
+ - Archive removes `INBOX` from a thread.
80
+ - Trash moves a thread to `TRASH`.
81
+ - Reset restores deterministic seeded state.
82
+
83
+ ## Fidelity Notes
84
+
85
+ The mock intentionally keeps all state in memory. It focuses on common Gmail workflows agents need to rehearse: reading, searching, drafting, sending, labeling, archiving, trashing, and reviewing threads. MIME parsing, OAuth, history diffs, watch notifications, batch requests, import/upload semantics, and exact Gmail search parity are deferred.
package/dist/api.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ import type { GmailMock } from "./service";
2
+ export interface GmailApiRequest {
3
+ method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
4
+ path: string;
5
+ query?: Record<string, string | number | boolean | string[] | undefined>;
6
+ body?: unknown;
7
+ }
8
+ export interface GmailApiResponse<T = unknown> {
9
+ status: number;
10
+ headers: Record<string, string>;
11
+ body?: T;
12
+ }
13
+ export declare function handleGmailApiRequest(mock: GmailMock, request: GmailApiRequest): GmailApiResponse;
14
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACzE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,OAAO;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,CAAC,CAAC;CACV;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,GAAG,gBAAgB,CASjG"}
package/dist/api.js ADDED
@@ -0,0 +1,139 @@
1
+ import { GmailMockError } from "./errors";
2
+ export function handleGmailApiRequest(mock, request) {
3
+ try {
4
+ return route(mock, request);
5
+ }
6
+ catch (error) {
7
+ if (error instanceof GmailMockError) {
8
+ return json(error.status, error.toJSON());
9
+ }
10
+ throw error;
11
+ }
12
+ }
13
+ function route(mock, request) {
14
+ const url = new URL(request.path, "https://gmail.googleapis.com");
15
+ const path = url.pathname.replace(/\/+$/, "");
16
+ const query = request.query ?? {};
17
+ if (request.method === "GET" && path === "/gmail/v1/users/me/profile") {
18
+ return json(200, mock.getProfile());
19
+ }
20
+ if (path === "/gmail/v1/users/me/labels") {
21
+ if (request.method === "GET")
22
+ return json(200, mock.listLabels());
23
+ if (request.method === "POST")
24
+ return json(200, mock.createLabel(request.body));
25
+ }
26
+ const labelMatch = path.match(/^\/gmail\/v1\/users\/me\/labels\/([^/]+)$/);
27
+ if (labelMatch) {
28
+ const id = decodeURIComponent(labelMatch[1]);
29
+ if (request.method === "GET")
30
+ return json(200, mock.getLabel(id));
31
+ if (request.method === "PUT" || request.method === "PATCH")
32
+ return json(200, mock.updateLabel(id, request.body));
33
+ if (request.method === "DELETE") {
34
+ mock.deleteLabel(id);
35
+ return { status: 204, headers: {} };
36
+ }
37
+ }
38
+ if (path === "/gmail/v1/users/me/messages") {
39
+ if (request.method === "GET")
40
+ return json(200, mock.listMessages(searchOptions(query)));
41
+ if (request.method === "POST")
42
+ return json(200, mock.insertMessage(request.body));
43
+ }
44
+ if (request.method === "POST" && path === "/gmail/v1/users/me/messages/send") {
45
+ return json(200, mock.send(request.body));
46
+ }
47
+ const messageActionMatch = path.match(/^\/gmail\/v1\/users\/me\/messages\/([^/]+)\/(modify|trash|untrash)$/);
48
+ if (messageActionMatch && request.method === "POST") {
49
+ const id = decodeURIComponent(messageActionMatch[1]);
50
+ const action = messageActionMatch[2];
51
+ if (action === "modify")
52
+ return json(200, mock.modifyMessage(id, request.body));
53
+ if (action === "trash")
54
+ return json(200, mock.trashMessage(id));
55
+ return json(200, mock.untrashMessage(id));
56
+ }
57
+ const messageMatch = path.match(/^\/gmail\/v1\/users\/me\/messages\/([^/]+)$/);
58
+ if (messageMatch) {
59
+ const id = decodeURIComponent(messageMatch[1]);
60
+ if (request.method === "GET")
61
+ return json(200, mock.getMessage(id));
62
+ if (request.method === "DELETE") {
63
+ mock.deleteMessage(id);
64
+ return { status: 204, headers: {} };
65
+ }
66
+ }
67
+ if (path === "/gmail/v1/users/me/threads" && request.method === "GET") {
68
+ return json(200, mock.listThreads(searchOptions(query)));
69
+ }
70
+ const threadActionMatch = path.match(/^\/gmail\/v1\/users\/me\/threads\/([^/]+)\/(modify|trash)$/);
71
+ if (threadActionMatch && request.method === "POST") {
72
+ const id = decodeURIComponent(threadActionMatch[1]);
73
+ return json(200, threadActionMatch[2] === "modify" ? mock.modifyThread(id, request.body) : mock.trashThread(id));
74
+ }
75
+ const threadMatch = path.match(/^\/gmail\/v1\/users\/me\/threads\/([^/]+)$/);
76
+ if (threadMatch && request.method === "GET") {
77
+ return json(200, mock.getThread(decodeURIComponent(threadMatch[1])));
78
+ }
79
+ if (path === "/gmail/v1/users/me/drafts") {
80
+ if (request.method === "GET")
81
+ return json(200, mock.listDrafts());
82
+ if (request.method === "POST")
83
+ return json(200, mock.createDraft(request.body));
84
+ }
85
+ const draftSendMatch = path.match(/^\/gmail\/v1\/users\/me\/drafts\/([^/]+)\/send$/);
86
+ if (draftSendMatch && request.method === "POST")
87
+ return json(200, mock.sendDraft(decodeURIComponent(draftSendMatch[1])));
88
+ const draftMatch = path.match(/^\/gmail\/v1\/users\/me\/drafts\/([^/]+)$/);
89
+ if (draftMatch) {
90
+ const id = decodeURIComponent(draftMatch[1]);
91
+ if (request.method === "GET")
92
+ return json(200, mock.getDraft(id));
93
+ if (request.method === "PUT")
94
+ return json(200, mock.updateDraft(id, request.body));
95
+ if (request.method === "DELETE") {
96
+ mock.deleteDraft(id);
97
+ return { status: 204, headers: {} };
98
+ }
99
+ }
100
+ return json(404, {
101
+ error: {
102
+ code: 404,
103
+ message: `Unsupported mock endpoint: ${request.method} ${request.path}`,
104
+ errors: [{ domain: "global", reason: "notFound", message: "Unsupported mock endpoint" }],
105
+ },
106
+ });
107
+ }
108
+ function json(status, body) {
109
+ return { status, headers: { "content-type": "application/json" }, body };
110
+ }
111
+ function searchOptions(query) {
112
+ return {
113
+ q: stringQuery(query?.q),
114
+ labelIds: arrayQuery(query?.labelIds),
115
+ includeSpamTrash: boolQuery(query?.includeSpamTrash),
116
+ maxResults: numberQuery(query?.maxResults),
117
+ };
118
+ }
119
+ function stringQuery(value) {
120
+ return Array.isArray(value) ? value[0] : value === undefined ? undefined : String(value);
121
+ }
122
+ function arrayQuery(value) {
123
+ if (Array.isArray(value))
124
+ return value.map(String);
125
+ if (typeof value === "string")
126
+ return value.split(",").filter(Boolean);
127
+ return undefined;
128
+ }
129
+ function boolQuery(value) {
130
+ if (value === undefined)
131
+ return undefined;
132
+ return value === true || value === "true";
133
+ }
134
+ function numberQuery(value) {
135
+ if (value === undefined || Array.isArray(value))
136
+ return undefined;
137
+ const parsed = Number(value);
138
+ return Number.isFinite(parsed) ? parsed : undefined;
139
+ }
@@ -0,0 +1,228 @@
1
+ import type { GmailMock } from "./service";
2
+ import type { GmailLabel, GmailMessage, GmailModifyRequest, GmailSearchOptions, GmailSendRequest } from "./types";
3
+ export declare function createGmailClient(mock: GmailMock): {
4
+ users: {
5
+ getProfile: ({ userId: _userId }?: {
6
+ userId?: string;
7
+ }) => Promise<{
8
+ data: import("./types").GmailProfile;
9
+ status: number;
10
+ statusText: string;
11
+ headers: {};
12
+ }>;
13
+ labels: {
14
+ list: ({ userId: _userId }?: {
15
+ userId?: string;
16
+ }) => Promise<{
17
+ data: import("./types").GmailListResponse<GmailLabel>;
18
+ status: number;
19
+ statusText: string;
20
+ headers: {};
21
+ }>;
22
+ get: ({ id }: {
23
+ userId?: string;
24
+ id: string;
25
+ }) => Promise<{
26
+ data: GmailLabel;
27
+ status: number;
28
+ statusText: string;
29
+ headers: {};
30
+ }>;
31
+ create: ({ requestBody }: {
32
+ userId?: string;
33
+ requestBody: Partial<GmailLabel>;
34
+ }) => Promise<{
35
+ data: GmailLabel;
36
+ status: number;
37
+ statusText: string;
38
+ headers: {};
39
+ }>;
40
+ update: ({ id, requestBody }: {
41
+ userId?: string;
42
+ id: string;
43
+ requestBody: Partial<GmailLabel>;
44
+ }) => Promise<{
45
+ data: GmailLabel;
46
+ status: number;
47
+ statusText: string;
48
+ headers: {};
49
+ }>;
50
+ delete: ({ id }: {
51
+ userId?: string;
52
+ id: string;
53
+ }) => Promise<{
54
+ data: undefined;
55
+ status: number;
56
+ statusText: string;
57
+ headers: {};
58
+ }>;
59
+ };
60
+ messages: {
61
+ list: (params?: GmailSearchOptions & {
62
+ userId?: string;
63
+ }) => Promise<{
64
+ data: import("./types").GmailListResponse<Pick<GmailMessage, "id" | "threadId">>;
65
+ status: number;
66
+ statusText: string;
67
+ headers: {};
68
+ }>;
69
+ get: ({ id }: {
70
+ userId?: string;
71
+ id: string;
72
+ }) => Promise<{
73
+ data: GmailMessage;
74
+ status: number;
75
+ statusText: string;
76
+ headers: {};
77
+ }>;
78
+ insert: ({ requestBody }: {
79
+ userId?: string;
80
+ requestBody: Partial<GmailMessage> | GmailSendRequest;
81
+ }) => Promise<{
82
+ data: GmailMessage;
83
+ status: number;
84
+ statusText: string;
85
+ headers: {};
86
+ }>;
87
+ send: ({ requestBody }: {
88
+ userId?: string;
89
+ requestBody: GmailSendRequest;
90
+ }) => Promise<{
91
+ data: GmailMessage;
92
+ status: number;
93
+ statusText: string;
94
+ headers: {};
95
+ }>;
96
+ modify: ({ id, requestBody }: {
97
+ userId?: string;
98
+ id: string;
99
+ requestBody: GmailModifyRequest;
100
+ }) => Promise<{
101
+ data: GmailMessage;
102
+ status: number;
103
+ statusText: string;
104
+ headers: {};
105
+ }>;
106
+ trash: ({ id }: {
107
+ userId?: string;
108
+ id: string;
109
+ }) => Promise<{
110
+ data: GmailMessage;
111
+ status: number;
112
+ statusText: string;
113
+ headers: {};
114
+ }>;
115
+ untrash: ({ id }: {
116
+ userId?: string;
117
+ id: string;
118
+ }) => Promise<{
119
+ data: GmailMessage;
120
+ status: number;
121
+ statusText: string;
122
+ headers: {};
123
+ }>;
124
+ delete: ({ id }: {
125
+ userId?: string;
126
+ id: string;
127
+ }) => Promise<{
128
+ data: undefined;
129
+ status: number;
130
+ statusText: string;
131
+ headers: {};
132
+ }>;
133
+ };
134
+ threads: {
135
+ list: (params?: GmailSearchOptions & {
136
+ userId?: string;
137
+ }) => Promise<{
138
+ data: import("./types").GmailListResponse<Pick<import("./types").GmailThread, "id" | "historyId" | "snippet">>;
139
+ status: number;
140
+ statusText: string;
141
+ headers: {};
142
+ }>;
143
+ get: ({ id }: {
144
+ userId?: string;
145
+ id: string;
146
+ }) => Promise<{
147
+ data: import("./types").GmailThread;
148
+ status: number;
149
+ statusText: string;
150
+ headers: {};
151
+ }>;
152
+ modify: ({ id, requestBody }: {
153
+ userId?: string;
154
+ id: string;
155
+ requestBody: GmailModifyRequest;
156
+ }) => Promise<{
157
+ data: import("./types").GmailThread;
158
+ status: number;
159
+ statusText: string;
160
+ headers: {};
161
+ }>;
162
+ trash: ({ id }: {
163
+ userId?: string;
164
+ id: string;
165
+ }) => Promise<{
166
+ data: import("./types").GmailThread;
167
+ status: number;
168
+ statusText: string;
169
+ headers: {};
170
+ }>;
171
+ };
172
+ drafts: {
173
+ list: () => Promise<{
174
+ data: import("./types").GmailListResponse<Pick<import("./types").GmailDraft, "id" | "message">>;
175
+ status: number;
176
+ statusText: string;
177
+ headers: {};
178
+ }>;
179
+ get: ({ id }: {
180
+ userId?: string;
181
+ id: string;
182
+ }) => Promise<{
183
+ data: import("./types").GmailDraft;
184
+ status: number;
185
+ statusText: string;
186
+ headers: {};
187
+ }>;
188
+ create: ({ requestBody }: {
189
+ userId?: string;
190
+ requestBody: GmailSendRequest;
191
+ }) => Promise<{
192
+ data: import("./types").GmailDraft;
193
+ status: number;
194
+ statusText: string;
195
+ headers: {};
196
+ }>;
197
+ update: ({ id, requestBody }: {
198
+ userId?: string;
199
+ id: string;
200
+ requestBody: GmailSendRequest;
201
+ }) => Promise<{
202
+ data: import("./types").GmailDraft;
203
+ status: number;
204
+ statusText: string;
205
+ headers: {};
206
+ }>;
207
+ send: ({ id }: {
208
+ userId?: string;
209
+ id: string;
210
+ }) => Promise<{
211
+ data: GmailMessage;
212
+ status: number;
213
+ statusText: string;
214
+ headers: {};
215
+ }>;
216
+ delete: ({ id }: {
217
+ userId?: string;
218
+ id: string;
219
+ }) => Promise<{
220
+ data: undefined;
221
+ status: number;
222
+ statusText: string;
223
+ headers: {};
224
+ }>;
225
+ };
226
+ };
227
+ };
228
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAMlH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS;;2CAGI;YAAE,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE;;;;;;;yCAEvB;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAA;aAAE;;;;;;0BACxC;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAA;aAAE;;;;;;sCACnB;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;aAAE;;;;;;0CACjD;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAC;gBAAC,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;aAAE;;;;;;6BAC9E;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAA;aAAE;;;;;;;;4BAMjC,kBAAkB,GAAG;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAA;aAAE;;;;;;0BACzC;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAA;aAAE;;;;;;sCACnB;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,WAAW,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,gBAAgB,CAAA;aAAE;;;;;;oCAC5E;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,WAAW,EAAE,gBAAgB,CAAA;aAAE;;;;;;0CAC5C;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAC;gBAAC,WAAW,EAAE,kBAAkB,CAAA;aAAE;;;;;;4BAC9E;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAA;aAAE;;;;;;8BAC7B;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAA;aAAE;;;;;;6BAChC;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAA;aAAE;;;;;;;;4BAMjC,kBAAkB,GAAG;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAA;aAAE;;;;;;0BACzC;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAA;aAAE;;;;;;0CACf;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAC;gBAAC,WAAW,EAAE,kBAAkB,CAAA;aAAE;;;;;;4BAC9E;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAA;aAAE;;;;;;;;;;;;;;0BAIjC;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAA;aAAE;;;;;;sCACnB;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,WAAW,EAAE,gBAAgB,CAAA;aAAE;;;;;;0CAC9C;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAC;gBAAC,WAAW,EAAE,gBAAgB,CAAA;aAAE;;;;;;2BAC7E;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAA;aAAE;;;;;;6BAC7B;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAA;aAAE;;;;;;;;EAO7D"}
package/dist/client.js ADDED
@@ -0,0 +1,50 @@
1
+ function response(data, status = 200, statusText = "OK") {
2
+ return { data, status, statusText, headers: {} };
3
+ }
4
+ export function createGmailClient(mock) {
5
+ return {
6
+ users: {
7
+ getProfile: async ({ userId: _userId = "me" } = {}) => response(mock.getProfile()),
8
+ labels: {
9
+ list: async ({ userId: _userId = "me" } = {}) => response(mock.listLabels()),
10
+ get: async ({ id }) => response(mock.getLabel(id)),
11
+ create: async ({ requestBody }) => response(mock.createLabel(requestBody)),
12
+ update: async ({ id, requestBody }) => response(mock.updateLabel(id, requestBody)),
13
+ delete: async ({ id }) => {
14
+ mock.deleteLabel(id);
15
+ return response(undefined, 204, "No Content");
16
+ },
17
+ },
18
+ messages: {
19
+ list: async (params = {}) => response(mock.listMessages(params)),
20
+ get: async ({ id }) => response(mock.getMessage(id)),
21
+ insert: async ({ requestBody }) => response(mock.insertMessage(requestBody)),
22
+ send: async ({ requestBody }) => response(mock.send(requestBody)),
23
+ modify: async ({ id, requestBody }) => response(mock.modifyMessage(id, requestBody)),
24
+ trash: async ({ id }) => response(mock.trashMessage(id)),
25
+ untrash: async ({ id }) => response(mock.untrashMessage(id)),
26
+ delete: async ({ id }) => {
27
+ mock.deleteMessage(id);
28
+ return response(undefined, 204, "No Content");
29
+ },
30
+ },
31
+ threads: {
32
+ list: async (params = {}) => response(mock.listThreads(params)),
33
+ get: async ({ id }) => response(mock.getThread(id)),
34
+ modify: async ({ id, requestBody }) => response(mock.modifyThread(id, requestBody)),
35
+ trash: async ({ id }) => response(mock.trashThread(id)),
36
+ },
37
+ drafts: {
38
+ list: async () => response(mock.listDrafts()),
39
+ get: async ({ id }) => response(mock.getDraft(id)),
40
+ create: async ({ requestBody }) => response(mock.createDraft(requestBody)),
41
+ update: async ({ id, requestBody }) => response(mock.updateDraft(id, requestBody)),
42
+ send: async ({ id }) => response(mock.sendDraft(id)),
43
+ delete: async ({ id }) => {
44
+ mock.deleteDraft(id);
45
+ return response(undefined, 204, "No Content");
46
+ },
47
+ },
48
+ },
49
+ };
50
+ }
@@ -0,0 +1,19 @@
1
+ export declare class GmailMockError extends Error {
2
+ readonly status: number;
3
+ readonly reason: string;
4
+ constructor(status: number, reason: string, message: string);
5
+ toJSON(): {
6
+ error: {
7
+ code: number;
8
+ message: string;
9
+ errors: {
10
+ domain: string;
11
+ reason: string;
12
+ message: string;
13
+ }[];
14
+ };
15
+ };
16
+ }
17
+ export declare function badRequest(message: string): GmailMockError;
18
+ export declare function notFound(message: string): GmailMockError;
19
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAO3D,MAAM;;;;;;;;;;;CASP;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAE1D;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAExD"}
package/dist/errors.js ADDED
@@ -0,0 +1,25 @@
1
+ export class GmailMockError extends Error {
2
+ status;
3
+ reason;
4
+ constructor(status, reason, message) {
5
+ super(message);
6
+ this.name = "GmailMockError";
7
+ this.status = status;
8
+ this.reason = reason;
9
+ }
10
+ toJSON() {
11
+ return {
12
+ error: {
13
+ code: this.status,
14
+ message: this.message,
15
+ errors: [{ domain: "global", reason: this.reason, message: this.message }],
16
+ },
17
+ };
18
+ }
19
+ }
20
+ export function badRequest(message) {
21
+ return new GmailMockError(400, "badRequest", message);
22
+ }
23
+ export function notFound(message) {
24
+ return new GmailMockError(404, "notFound", message);
25
+ }
@@ -0,0 +1,10 @@
1
+ export { handleGmailApiRequest } from "./api";
2
+ export type { GmailApiRequest, GmailApiResponse } from "./api";
3
+ export { createGmailClient } from "./client";
4
+ export { GmailMockError } from "./errors";
5
+ export { decodeBase64Url, encodeBase64Url, GmailMock } from "./service";
6
+ import { GmailMock } from "./service";
7
+ export { demoDrafts, demoMessages, demoSeed, demoUser } from "./seed";
8
+ export type * from "./types";
9
+ export declare function createGmailMock(...args: ConstructorParameters<typeof GmailMock>): GmailMock;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACtE,mBAAmB,SAAS,CAAC;AAE7B,wBAAgB,eAAe,CAAC,GAAG,IAAI,EAAE,qBAAqB,CAAC,OAAO,SAAS,CAAC,GAAG,SAAS,CAE3F"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export { handleGmailApiRequest } from "./api";
2
+ export { createGmailClient } from "./client";
3
+ export { GmailMockError } from "./errors";
4
+ export { decodeBase64Url, encodeBase64Url, GmailMock } from "./service";
5
+ import { GmailMock } from "./service";
6
+ export { demoDrafts, demoMessages, demoSeed, demoUser } from "./seed";
7
+ export function createGmailMock(...args) {
8
+ return new GmailMock(...args);
9
+ }
package/dist/seed.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import type { GmailDraft, GmailMessage, GmailSeed, GmailUser } from "./types";
2
+ export declare const demoUser: GmailUser;
3
+ export declare const demoMessages: GmailMessage[];
4
+ export declare const demoDrafts: GmailDraft[];
5
+ export declare const demoSeed: GmailSeed;
6
+ //# sourceMappingURL=seed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../src/seed.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAE9E,eAAO,MAAM,QAAQ,EAAE,SAItB,CAAC;AAgDF,eAAO,MAAM,YAAY,EAAE,YAAY,EAiDtC,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,UAAU,EAalC,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,SAoBtB,CAAC"}