@marcoappio/marco-config 2.0.508 → 2.0.510

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 (105) hide show
  1. package/dist/constants/index.d.ts +1 -0
  2. package/dist/constants/index.d.ts.map +1 -1
  3. package/dist/constants/zero.d.ts +1 -0
  4. package/dist/constants/zero.d.ts.map +1 -1
  5. package/dist/constants/zero.js +1 -0
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/types/Zero.d.ts +0 -17
  9. package/dist/types/Zero.d.ts.map +1 -1
  10. package/dist/zero/index.d.ts +2903 -8808
  11. package/dist/zero/index.d.ts.map +1 -1
  12. package/dist/zero/index.js +6 -17
  13. package/dist/zero/{queries/getThreadList.d.ts → mutators.d.ts} +572 -169
  14. package/dist/zero/{queries/getThreads.d.ts.map → mutators.d.ts.map} +1 -1
  15. package/dist/zero/mutators.js +659 -0
  16. package/dist/zero/mutators.test.d.ts +2 -0
  17. package/dist/zero/mutators.test.d.ts.map +1 -0
  18. package/dist/zero/mutators.test.js +603 -0
  19. package/dist/zero/{queries/getThreads.d.ts → queries.d.ts} +481 -196
  20. package/dist/zero/{queries/getThread.d.ts.map → queries.d.ts.map} +1 -1
  21. package/dist/zero/queries.js +168 -0
  22. package/dist/zero/schema.d.ts +138 -133
  23. package/dist/zero/schema.d.ts.map +1 -1
  24. package/dist/zero/schema.js +1 -1
  25. package/package.json +3 -3
  26. package/dist/zero/mutatorSchemas/account.d.ts +0 -80
  27. package/dist/zero/mutatorSchemas/account.d.ts.map +0 -1
  28. package/dist/zero/mutatorSchemas/account.js +0 -66
  29. package/dist/zero/mutatorSchemas/draft.d.ts +0 -150
  30. package/dist/zero/mutatorSchemas/draft.d.ts.map +0 -1
  31. package/dist/zero/mutatorSchemas/draft.js +0 -104
  32. package/dist/zero/mutatorSchemas/index.d.ts +0 -323
  33. package/dist/zero/mutatorSchemas/index.d.ts.map +0 -1
  34. package/dist/zero/mutatorSchemas/index.js +0 -10
  35. package/dist/zero/mutatorSchemas/thread.d.ts +0 -71
  36. package/dist/zero/mutatorSchemas/thread.d.ts.map +0 -1
  37. package/dist/zero/mutatorSchemas/thread.js +0 -47
  38. package/dist/zero/mutatorSchemas/user.d.ts +0 -26
  39. package/dist/zero/mutatorSchemas/user.d.ts.map +0 -1
  40. package/dist/zero/mutatorSchemas/user.js +0 -27
  41. package/dist/zero/mutators/accountMutators/accountMutators.d.ts +0 -4
  42. package/dist/zero/mutators/accountMutators/accountMutators.d.ts.map +0 -1
  43. package/dist/zero/mutators/accountMutators/accountMutators.js +0 -103
  44. package/dist/zero/mutators/accountMutators/accountMutators.test.d.ts +0 -2
  45. package/dist/zero/mutators/accountMutators/accountMutators.test.d.ts.map +0 -1
  46. package/dist/zero/mutators/accountMutators/accountMutators.test.js +0 -372
  47. package/dist/zero/mutators/accountMutators/index.d.ts +0 -2
  48. package/dist/zero/mutators/accountMutators/index.d.ts.map +0 -1
  49. package/dist/zero/mutators/accountMutators/index.js +0 -1
  50. package/dist/zero/mutators/draftMutators/draftMutators.d.ts +0 -4
  51. package/dist/zero/mutators/draftMutators/draftMutators.d.ts.map +0 -1
  52. package/dist/zero/mutators/draftMutators/draftMutators.js +0 -142
  53. package/dist/zero/mutators/draftMutators/draftMutators.test.d.ts +0 -2
  54. package/dist/zero/mutators/draftMutators/draftMutators.test.d.ts.map +0 -1
  55. package/dist/zero/mutators/draftMutators/draftMutators.test.js +0 -416
  56. package/dist/zero/mutators/draftMutators/index.d.ts +0 -2
  57. package/dist/zero/mutators/draftMutators/index.d.ts.map +0 -1
  58. package/dist/zero/mutators/draftMutators/index.js +0 -1
  59. package/dist/zero/mutators/index.d.ts +0 -3
  60. package/dist/zero/mutators/index.d.ts.map +0 -1
  61. package/dist/zero/mutators/index.js +0 -1
  62. package/dist/zero/mutators/mutators.d.ts +0 -18
  63. package/dist/zero/mutators/mutators.d.ts.map +0 -1
  64. package/dist/zero/mutators/mutators.js +0 -39
  65. package/dist/zero/mutators/threadMutators/index.d.ts +0 -2
  66. package/dist/zero/mutators/threadMutators/index.d.ts.map +0 -1
  67. package/dist/zero/mutators/threadMutators/index.js +0 -1
  68. package/dist/zero/mutators/threadMutators/threadMutators.d.ts +0 -8
  69. package/dist/zero/mutators/threadMutators/threadMutators.d.ts.map +0 -1
  70. package/dist/zero/mutators/threadMutators/threadMutators.js +0 -257
  71. package/dist/zero/mutators/threadMutators/threadMutators.test.d.ts +0 -2
  72. package/dist/zero/mutators/threadMutators/threadMutators.test.d.ts.map +0 -1
  73. package/dist/zero/mutators/threadMutators/threadMutators.test.js +0 -755
  74. package/dist/zero/mutators/userMutators/index.d.ts +0 -2
  75. package/dist/zero/mutators/userMutators/index.d.ts.map +0 -1
  76. package/dist/zero/mutators/userMutators/index.js +0 -1
  77. package/dist/zero/mutators/userMutators/userMutators.d.ts +0 -4
  78. package/dist/zero/mutators/userMutators/userMutators.d.ts.map +0 -1
  79. package/dist/zero/mutators/userMutators/userMutators.js +0 -28
  80. package/dist/zero/mutators/userMutators/userMutators.test.d.ts +0 -2
  81. package/dist/zero/mutators/userMutators/userMutators.test.d.ts.map +0 -1
  82. package/dist/zero/mutators/userMutators/userMutators.test.js +0 -84
  83. package/dist/zero/queries/getAccounts.d.ts +0 -1060
  84. package/dist/zero/queries/getAccounts.d.ts.map +0 -1
  85. package/dist/zero/queries/getAccounts.js +0 -3
  86. package/dist/zero/queries/getContacts.d.ts +0 -1040
  87. package/dist/zero/queries/getContacts.d.ts.map +0 -1
  88. package/dist/zero/queries/getContacts.js +0 -37
  89. package/dist/zero/queries/getDrafts.d.ts +0 -1061
  90. package/dist/zero/queries/getDrafts.d.ts.map +0 -1
  91. package/dist/zero/queries/getDrafts.js +0 -24
  92. package/dist/zero/queries/getThread.d.ts +0 -1072
  93. package/dist/zero/queries/getThread.js +0 -14
  94. package/dist/zero/queries/getThreadByMessageId.d.ts +0 -1056
  95. package/dist/zero/queries/getThreadByMessageId.d.ts.map +0 -1
  96. package/dist/zero/queries/getThreadByMessageId.js +0 -13
  97. package/dist/zero/queries/getThreadList.d.ts.map +0 -1
  98. package/dist/zero/queries/getThreadList.js +0 -57
  99. package/dist/zero/queries/getThreads.js +0 -59
  100. package/dist/zero/queries/getUser.d.ts +0 -1074
  101. package/dist/zero/queries/getUser.d.ts.map +0 -1
  102. package/dist/zero/queries/getUser.js +0 -7
  103. package/dist/zero/queries/index.d.ts +0 -1032
  104. package/dist/zero/queries/index.d.ts.map +0 -1
  105. package/dist/zero/queries/index.js +0 -11
@@ -1 +1 @@
1
- {"version":3,"file":"getThreads.d.ts","sourceRoot":"","sources":["../../../src/zero/queries/getThreads.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAOlE,KAAK,cAAc,GAAG;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE;QACN,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,EAAE,CAAC,EAAE,MAAM,CAAA;QACX,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;QACrB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;QACvB,IAAI,CAAC,EAAE,OAAO,CAAA;KACf,CAAA;CACF,CAAA;AAoBD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDtB,CAAA"}
1
+ {"version":3,"file":"mutators.d.ts","sourceRoot":"","sources":["../../src/zero/mutators.ts"],"names":[],"mappings":"AAWA,KAAK,OAAO,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAqJjC,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAysBnB,CAAA"}
@@ -0,0 +1,659 @@
1
+ import { createBuilder, defineMutators, defineMutatorWithType } from '@rocicorp/zero';
2
+ import * as v from 'valibot';
3
+ import { marcoSchemas } from '../schemas';
4
+ import { DRAFT_ATTACHMENT_UPLOAD_STATUSES, DRAFT_STATUSES, DRAFT_TYPES, MutationError } from '../types';
5
+ import { stringPatch } from '../utils';
6
+ import { threadsUtils } from '../utils/threads';
7
+ import { schema } from './schema';
8
+ const zql = createBuilder(schema);
9
+ const defineMutator = defineMutatorWithType();
10
+ const accountAliasSchema = v.object({
11
+ emailAddress: marcoSchemas.string.email(),
12
+ id: marcoSchemas.string.required(),
13
+ name: marcoSchemas.string.nullable(),
14
+ });
15
+ const accountsSchema = v.record(marcoSchemas.string.required(), v.object({
16
+ threadIds: v.array(marcoSchemas.string.required()),
17
+ }));
18
+ const baseThreadSchema = v.object({
19
+ accounts: accountsSchema,
20
+ });
21
+ const threadChangeLabelSchema = v.object({
22
+ accounts: accountsSchema,
23
+ labelPath: marcoSchemas.string.required(),
24
+ });
25
+ const draftBodySchema = v.object({
26
+ bcc: v.array(marcoSchemas.string.email()),
27
+ cc: v.array(marcoSchemas.string.email()),
28
+ content: v.pipe(v.string(), v.maxLength(384000)),
29
+ subject: marcoSchemas.string.nullable(),
30
+ to: v.array(marcoSchemas.string.email()),
31
+ });
32
+ const draftAttachmentSchema = v.object({
33
+ fileName: marcoSchemas.string.required(),
34
+ id: marcoSchemas.string.required(),
35
+ mimeType: marcoSchemas.string.required(),
36
+ status: v.picklist(DRAFT_ATTACHMENT_UPLOAD_STATUSES),
37
+ totalSize: marcoSchemas.number.positiveInteger(),
38
+ });
39
+ const userPushNotificationTokenSchema = v.object({
40
+ createdAt: marcoSchemas.number.positiveInteger(),
41
+ id: marcoSchemas.string.required(),
42
+ token: marcoSchemas.string.required(),
43
+ });
44
+ const buildLabelIdList = (x) => (x.length === 0 ? '' : ` ${[...new Set(x)].join(' ')} `);
45
+ const setSystemLabel = async (tx, builder, threadId, targetSpecialUse) => {
46
+ const thread = await tx.run(builder.thread.where('id', threadId).one());
47
+ if (!thread) {
48
+ throw new Error(MutationError.ENTITY_NOT_FOUND);
49
+ }
50
+ const [targetLabel, messages] = await Promise.all([
51
+ tx.run(builder.accountLabel.where('accountId', thread.accountId).where('specialUse', targetSpecialUse).one()),
52
+ tx.run(builder.threadMessage.where('threadId', threadId)),
53
+ ]);
54
+ if (!targetLabel) {
55
+ throw new Error(MutationError.ENTITY_NOT_FOUND);
56
+ }
57
+ const currentLabelIds = new Set(threadsUtils.parseLabelIdList(thread.labelIdList));
58
+ const hasTarget = currentLabelIds.has(targetLabel.id);
59
+ const labelIdsToRemove = new Set(currentLabelIds);
60
+ labelIdsToRemove.delete(targetLabel.id);
61
+ const threadLabelDeletes = [];
62
+ for (const message of messages) {
63
+ for (const labelId of labelIdsToRemove) {
64
+ threadLabelDeletes.push(tx.mutate.threadLabel.delete({
65
+ accountId: thread.accountId,
66
+ labelId,
67
+ threadMessageId: message.id,
68
+ }));
69
+ }
70
+ }
71
+ await Promise.all([
72
+ ...threadLabelDeletes,
73
+ ...[...labelIdsToRemove].map(labelId => tx.mutate.threadByLabel.delete({ labelId, threadId })),
74
+ ]);
75
+ if (thread.seen === false && labelIdsToRemove.size > 0) {
76
+ const labelsToUpdate = await tx.run(builder.accountLabel.where('id', 'IN', [...labelIdsToRemove]));
77
+ await Promise.all(labelsToUpdate.map(label => tx.mutate.accountLabel.update({
78
+ id: label.id,
79
+ unreadCount: Math.max(0, (label.unreadCount ?? 0) - 1),
80
+ })));
81
+ }
82
+ if (!hasTarget) {
83
+ const baseTimestamp = Date.now();
84
+ await Promise.all([
85
+ ...messages.map((message, i) => tx.mutate.threadLabel.insert({
86
+ accountId: thread.accountId,
87
+ labelId: targetLabel.id,
88
+ lastSyncedAt: 0,
89
+ threadId,
90
+ threadMessageId: message.id,
91
+ uid: -(baseTimestamp + i),
92
+ uidValidity: targetLabel.uidValidity ?? 0,
93
+ })),
94
+ tx.mutate.threadByLabel.insert({
95
+ labelId: targetLabel.id,
96
+ latestMessageDate: thread.latestMessageDate,
97
+ threadId,
98
+ }),
99
+ ...(thread.seen === false
100
+ ? [
101
+ tx.mutate.accountLabel.update({
102
+ id: targetLabel.id,
103
+ unreadCount: (targetLabel.unreadCount ?? 0) + 1,
104
+ }),
105
+ ]
106
+ : []),
107
+ ]);
108
+ }
109
+ await tx.mutate.thread.update({
110
+ id: threadId,
111
+ labelIdList: buildLabelIdList([targetLabel.id]),
112
+ });
113
+ };
114
+ export const mutators = defineMutators({
115
+ account: {
116
+ createAccount: defineMutator(v.object({
117
+ aliasId: marcoSchemas.string.required(),
118
+ color: marcoSchemas.string.required(),
119
+ emailAddress: marcoSchemas.string.email(),
120
+ id: marcoSchemas.string.required(),
121
+ }), async ({ tx, ctx, args }) => {
122
+ await tx.mutate.account.insert({
123
+ color: args.color,
124
+ displayName: null,
125
+ id: args.id,
126
+ imapConnectionStatus: 'AWAITING_CONNECTION',
127
+ mailProcessedCount: 0,
128
+ mailTotalCount: 0,
129
+ primaryAliasId: args.aliasId,
130
+ userId: ctx.userId,
131
+ });
132
+ await tx.mutate.accountAlias.insert({
133
+ accountId: args.id,
134
+ emailAddress: args.emailAddress,
135
+ id: args.aliasId,
136
+ isPrimary: true,
137
+ name: null,
138
+ });
139
+ }),
140
+ createAlias: defineMutator(v.object({
141
+ accountId: marcoSchemas.string.required(),
142
+ alias: accountAliasSchema,
143
+ }), async ({ tx, args }) => {
144
+ await tx.mutate.accountAlias.insert({
145
+ accountId: args.accountId,
146
+ emailAddress: args.alias.emailAddress,
147
+ id: args.alias.id,
148
+ isPrimary: false,
149
+ name: args.alias.name ?? null,
150
+ });
151
+ }),
152
+ deleteAccount: defineMutator(v.object({
153
+ id: marcoSchemas.string.required(),
154
+ }), async ({ tx, args }) => {
155
+ await tx.mutate.account.delete({
156
+ id: args.id,
157
+ });
158
+ }),
159
+ deleteAlias: defineMutator(v.object({
160
+ accountId: marcoSchemas.string.required(),
161
+ aliasId: marcoSchemas.string.required(),
162
+ }), async ({ tx, args }) => {
163
+ const alias = await tx.run(zql.accountAlias.where('id', args.aliasId).one());
164
+ await tx.mutate.accountAlias.delete({
165
+ id: args.aliasId,
166
+ });
167
+ if (alias?.isPrimary) {
168
+ const remainingAliases = await tx.run(zql.accountAlias.where('accountId', args.accountId));
169
+ if (remainingAliases.length > 0) {
170
+ const newPrimaryAlias = remainingAliases[0];
171
+ await tx.mutate.accountAlias.update({
172
+ id: newPrimaryAlias.id,
173
+ isPrimary: true,
174
+ });
175
+ await tx.mutate.account.update({
176
+ id: args.accountId,
177
+ primaryAliasId: newPrimaryAlias.id,
178
+ });
179
+ }
180
+ else {
181
+ await tx.mutate.account.update({
182
+ id: args.accountId,
183
+ primaryAliasId: null,
184
+ });
185
+ }
186
+ }
187
+ }),
188
+ setAliasName: defineMutator(v.object({
189
+ accountId: marcoSchemas.string.required(),
190
+ aliasId: marcoSchemas.string.required(),
191
+ displayName: marcoSchemas.string.nullable(),
192
+ }), async ({ tx, args }) => {
193
+ await tx.mutate.accountAlias.update({
194
+ id: args.aliasId,
195
+ name: args.displayName,
196
+ });
197
+ }),
198
+ setAliasPrimary: defineMutator(v.object({
199
+ accountId: marcoSchemas.string.required(),
200
+ aliasId: marcoSchemas.string.required(),
201
+ }), async ({ tx, args }) => {
202
+ const aliases = await tx.run(zql.accountAlias.where('accountId', args.accountId));
203
+ for (const alias of aliases) {
204
+ await tx.mutate.accountAlias.update({
205
+ id: alias.id,
206
+ isPrimary: alias.id === args.aliasId,
207
+ });
208
+ }
209
+ await tx.mutate.account.update({
210
+ id: args.accountId,
211
+ primaryAliasId: args.aliasId,
212
+ });
213
+ }),
214
+ setConnectionConfigImapRaw: defineMutator(v.object({
215
+ connectionConfig: marcoSchemas.emailAccount.connectionConfigImapRaw(),
216
+ id: marcoSchemas.string.required(),
217
+ }), async ({ tx, args }) => {
218
+ await tx.mutate.account.update({
219
+ id: args.id,
220
+ imapConnectionStatus: 'AWAITING_CONNECTION',
221
+ });
222
+ }),
223
+ setConnectionConfigOauth: defineMutator(v.object({
224
+ connectionConfig: marcoSchemas.emailAccount.connectionConfigOauth(),
225
+ id: marcoSchemas.string.required(),
226
+ }), async ({ tx, args }) => {
227
+ await tx.mutate.account.update({
228
+ id: args.id,
229
+ imapConnectionStatus: 'AWAITING_CONNECTION',
230
+ });
231
+ }),
232
+ setSettings: defineMutator(v.object({
233
+ color: v.optional(marcoSchemas.string.nullable()),
234
+ displayName: v.optional(marcoSchemas.string.nullable()),
235
+ id: marcoSchemas.string.required(),
236
+ }), async ({ tx, args }) => {
237
+ await tx.mutate.account.update({
238
+ color: args.color ? args.color : undefined,
239
+ displayName: args.displayName ? args.displayName : undefined,
240
+ id: args.id,
241
+ });
242
+ }),
243
+ },
244
+ draft: {
245
+ cancelSend: defineMutator(v.object({
246
+ id: marcoSchemas.string.required(),
247
+ updatedAt: marcoSchemas.number.positiveInteger(),
248
+ }), async ({ tx, args }) => {
249
+ const draft = await tx.run(zql.draft.where('id', args.id).one());
250
+ if (!draft) {
251
+ throw new Error(MutationError.ENTITY_NOT_FOUND);
252
+ }
253
+ if (draft.status === 'SEND_CONFIRMED') {
254
+ throw new Error(MutationError.ALREADY_APPLIED);
255
+ }
256
+ await tx.mutate.draft.update({
257
+ id: args.id,
258
+ scheduledFor: null,
259
+ status: 'DRAFT',
260
+ updatedAt: args.updatedAt,
261
+ });
262
+ }),
263
+ createAttachment: defineMutator(v.object({
264
+ attachment: draftAttachmentSchema,
265
+ id: marcoSchemas.string.required(),
266
+ updatedAt: marcoSchemas.number.positiveInteger(),
267
+ }), async ({ tx, args }) => {
268
+ await tx.mutate.draftAttachment.insert({
269
+ draftId: args.id,
270
+ fileName: args.attachment.fileName,
271
+ id: args.attachment.id,
272
+ mimeType: args.attachment.mimeType,
273
+ status: args.attachment.status,
274
+ totalSize: args.attachment.totalSize,
275
+ });
276
+ await tx.mutate.draft.update({
277
+ id: args.id,
278
+ updatedAt: args.updatedAt,
279
+ });
280
+ }),
281
+ createDraft: defineMutator(v.object({
282
+ accountId: marcoSchemas.string.required(),
283
+ attachments: v.array(draftAttachmentSchema),
284
+ body: draftBodySchema,
285
+ error: marcoSchemas.string.nullable(),
286
+ from: marcoSchemas.string.email(),
287
+ fromName: marcoSchemas.string.nullable(),
288
+ id: marcoSchemas.string.required(),
289
+ referencedMessageId: marcoSchemas.string.nullable(),
290
+ scheduledFor: v.nullable(marcoSchemas.number.positiveInteger()),
291
+ status: v.picklist(DRAFT_STATUSES),
292
+ type: v.picklist(DRAFT_TYPES),
293
+ updatedAt: marcoSchemas.number.positiveInteger(),
294
+ }), async ({ tx, ctx, args }) => {
295
+ await tx.mutate.draft.insert({
296
+ accountId: args.accountId,
297
+ body: {
298
+ bcc: args.body.bcc,
299
+ cc: args.body.cc,
300
+ content: args.body.content,
301
+ to: args.body.to,
302
+ },
303
+ error: args.error,
304
+ fromAliasId: null,
305
+ fromEmail: args.from,
306
+ fromName: args.fromName,
307
+ id: args.id,
308
+ referencedMessageId: args.referencedMessageId,
309
+ scheduledFor: args.scheduledFor,
310
+ status: args.status,
311
+ subject: args.body.subject,
312
+ type: args.type,
313
+ updatedAt: args.updatedAt,
314
+ userId: ctx.userId,
315
+ });
316
+ for (const attachment of args.attachments) {
317
+ await tx.mutate.draftAttachment.insert({
318
+ draftId: args.id,
319
+ fileName: attachment.fileName,
320
+ id: attachment.id,
321
+ mimeType: attachment.mimeType,
322
+ status: attachment.status,
323
+ totalSize: attachment.totalSize,
324
+ });
325
+ }
326
+ }),
327
+ deleteAttachment: defineMutator(v.object({
328
+ attachmentId: marcoSchemas.string.required(),
329
+ id: marcoSchemas.string.required(),
330
+ updatedAt: marcoSchemas.number.positiveInteger(),
331
+ }), async ({ tx, args }) => {
332
+ await tx.mutate.draftAttachment.delete({
333
+ id: args.attachmentId,
334
+ });
335
+ await tx.mutate.draft.update({
336
+ id: args.id,
337
+ updatedAt: args.updatedAt,
338
+ });
339
+ }),
340
+ deleteDraft: defineMutator(v.object({
341
+ id: marcoSchemas.string.required(),
342
+ }), async ({ tx, args }) => {
343
+ await tx.mutate.draft.delete({
344
+ id: args.id,
345
+ });
346
+ }),
347
+ scheduleSend: defineMutator(v.union([
348
+ v.object({
349
+ id: marcoSchemas.string.required(),
350
+ kind: v.literal('IMMEDIATE'),
351
+ undoMs: marcoSchemas.number.positiveInteger(),
352
+ updatedAt: marcoSchemas.number.positiveInteger(),
353
+ }),
354
+ v.object({
355
+ id: marcoSchemas.string.required(),
356
+ kind: v.literal('SCHEDULED'),
357
+ scheduledFor: marcoSchemas.number.positiveInteger(),
358
+ updatedAt: marcoSchemas.number.positiveInteger(),
359
+ }),
360
+ ]), async ({ tx, args }) => {
361
+ if (args.kind === 'IMMEDIATE') {
362
+ await tx.mutate.draft.update({
363
+ id: args.id,
364
+ scheduledFor: args.updatedAt + args.undoMs,
365
+ status: 'SEND_REQUESTED',
366
+ updatedAt: args.updatedAt,
367
+ });
368
+ }
369
+ else {
370
+ await tx.mutate.draft.update({
371
+ id: args.id,
372
+ scheduledFor: args.scheduledFor,
373
+ status: 'SEND_REQUESTED',
374
+ updatedAt: args.updatedAt,
375
+ });
376
+ }
377
+ }),
378
+ setContent: defineMutator(v.object({
379
+ id: marcoSchemas.string.required(),
380
+ patch: marcoSchemas.drafts.contentPatch.patch(),
381
+ updatedAt: marcoSchemas.number.positiveInteger(),
382
+ }), async ({ tx, args }) => {
383
+ const draft = await tx.run(zql.draft.where('id', args.id).one());
384
+ if (!draft) {
385
+ throw new Error(MutationError.ENTITY_NOT_FOUND);
386
+ }
387
+ await tx.mutate.draft.update({
388
+ body: {
389
+ ...draft.body,
390
+ content: stringPatch.apply(typeof draft.body?.content === 'string' ? draft.body.content : '', args.patch),
391
+ },
392
+ id: args.id,
393
+ updatedAt: args.updatedAt,
394
+ });
395
+ }),
396
+ setEnvelope: defineMutator(v.object({
397
+ envelope: v.omit(draftBodySchema, ['content']),
398
+ id: marcoSchemas.string.required(),
399
+ updatedAt: marcoSchemas.number.positiveInteger(),
400
+ }), async ({ tx, args }) => {
401
+ const draft = await tx.run(zql.draft.where('id', args.id).one());
402
+ if (!draft) {
403
+ throw new Error(MutationError.ENTITY_NOT_FOUND);
404
+ }
405
+ await tx.mutate.draft.update({
406
+ body: {
407
+ bcc: args.envelope.bcc,
408
+ cc: args.envelope.cc,
409
+ content: draft.body.content,
410
+ to: args.envelope.to,
411
+ },
412
+ id: args.id,
413
+ subject: args.envelope.subject,
414
+ updatedAt: args.updatedAt,
415
+ });
416
+ }),
417
+ setFrom: defineMutator(v.object({
418
+ accountId: marcoSchemas.string.required(),
419
+ aliasId: marcoSchemas.string.required(),
420
+ from: marcoSchemas.string.email(),
421
+ fromName: marcoSchemas.string.nullable(),
422
+ id: marcoSchemas.string.required(),
423
+ updatedAt: marcoSchemas.number.positiveInteger(),
424
+ }), async ({ tx, args }) => {
425
+ await tx.mutate.draft.update({
426
+ accountId: args.accountId,
427
+ fromAliasId: args.aliasId,
428
+ fromEmail: args.from,
429
+ fromName: args.fromName,
430
+ id: args.id,
431
+ updatedAt: args.updatedAt,
432
+ });
433
+ }),
434
+ },
435
+ thread: {
436
+ addLabel: defineMutator(threadChangeLabelSchema, async ({ tx, args }) => {
437
+ for (const [accountId, { threadIds }] of Object.entries(args.accounts)) {
438
+ const label = await tx.run(zql.accountLabel.where('accountId', accountId).where('path', args.labelPath).one());
439
+ if (!label) {
440
+ throw new Error(MutationError.ENTITY_NOT_FOUND);
441
+ }
442
+ for (const threadId of threadIds) {
443
+ const [thread, messages] = await Promise.all([
444
+ tx.run(zql.thread.where('id', threadId).one()),
445
+ tx.run(zql.threadMessage.where('threadId', threadId)),
446
+ ]);
447
+ if (!thread) {
448
+ throw new Error(MutationError.ENTITY_NOT_FOUND);
449
+ }
450
+ const currentLabelIds = new Set(threadsUtils.parseLabelIdList(thread.labelIdList));
451
+ if (!currentLabelIds.has(label.id)) {
452
+ await Promise.all([
453
+ tx.mutate.threadByLabel.insert({
454
+ labelId: label.id,
455
+ latestMessageDate: thread.latestMessageDate,
456
+ threadId,
457
+ }),
458
+ ...(thread.seen === false
459
+ ? [
460
+ tx.mutate.accountLabel.update({
461
+ id: label.id,
462
+ unreadCount: (label.unreadCount ?? 0) + 1,
463
+ }),
464
+ ]
465
+ : []),
466
+ ]);
467
+ }
468
+ const existingChecks = await Promise.all(messages.map(x => tx.run(zql.threadLabel.where('threadMessageId', x.id).where('labelId', label.id).one())));
469
+ const messagesToInsert = messages.filter((_, i) => !existingChecks[i]);
470
+ const baseTimestamp = Date.now();
471
+ if (messagesToInsert.length > 0) {
472
+ await Promise.all(messagesToInsert.map((x, i) => tx.mutate.threadLabel.insert({
473
+ accountId,
474
+ labelId: label.id,
475
+ lastSyncedAt: 0,
476
+ threadId,
477
+ threadMessageId: x.id,
478
+ uid: -(baseTimestamp + i),
479
+ uidValidity: label.uidValidity ?? 0,
480
+ })));
481
+ }
482
+ currentLabelIds.add(label.id);
483
+ await tx.mutate.thread.update({
484
+ id: threadId,
485
+ labelIdList: buildLabelIdList([...currentLabelIds]),
486
+ });
487
+ }
488
+ }
489
+ }),
490
+ delete: defineMutator(baseThreadSchema, async ({ tx, args }) => {
491
+ for (const [, { threadIds }] of Object.entries(args.accounts)) {
492
+ for (const threadId of threadIds) {
493
+ const thread = await tx.run(zql.thread.where('id', threadId).one());
494
+ if (thread) {
495
+ if (thread.seen === false) {
496
+ const labelIds = threadsUtils.parseLabelIdList(thread.labelIdList);
497
+ if (labelIds.length > 0) {
498
+ const labels = await tx.run(zql.accountLabel.where('id', 'IN', labelIds));
499
+ await Promise.all(labels.map(x => tx.mutate.accountLabel.update({
500
+ id: x.id,
501
+ unreadCount: Math.max(0, (x.unreadCount ?? 0) - 1),
502
+ })));
503
+ }
504
+ }
505
+ await tx.mutate.thread.delete({
506
+ id: threadId,
507
+ });
508
+ }
509
+ }
510
+ }
511
+ }),
512
+ removeLabel: defineMutator(threadChangeLabelSchema, async ({ tx, args }) => {
513
+ for (const [accountId, { threadIds }] of Object.entries(args.accounts)) {
514
+ const label = await tx.run(zql.accountLabel.where('accountId', accountId).where('path', args.labelPath).one());
515
+ if (!label) {
516
+ throw new Error(MutationError.ENTITY_NOT_FOUND);
517
+ }
518
+ for (const threadId of threadIds) {
519
+ const [thread, messages] = await Promise.all([
520
+ tx.run(zql.thread.where('id', threadId).one()),
521
+ tx.run(zql.threadMessage.where('threadId', threadId)),
522
+ ]);
523
+ if (!thread) {
524
+ throw new Error(MutationError.ENTITY_NOT_FOUND);
525
+ }
526
+ const currentLabelIds = new Set(threadsUtils.parseLabelIdList(thread.labelIdList));
527
+ if (!currentLabelIds.has(label.id)) {
528
+ throw new Error(MutationError.ENTITY_NOT_FOUND);
529
+ }
530
+ currentLabelIds.delete(label.id);
531
+ await Promise.all([
532
+ ...messages.map(x => tx.mutate.threadLabel.delete({
533
+ accountId,
534
+ labelId: label.id,
535
+ threadMessageId: x.id,
536
+ })),
537
+ tx.mutate.threadByLabel.delete({
538
+ labelId: label.id,
539
+ threadId,
540
+ }),
541
+ ...(thread.seen === false
542
+ ? [
543
+ tx.mutate.accountLabel.update({
544
+ id: label.id,
545
+ unreadCount: Math.max(0, (label.unreadCount ?? 0) - 1),
546
+ }),
547
+ ]
548
+ : []),
549
+ tx.mutate.thread.update({
550
+ id: threadId,
551
+ labelIdList: buildLabelIdList([...currentLabelIds]),
552
+ }),
553
+ ]);
554
+ }
555
+ }
556
+ }),
557
+ setArchive: defineMutator(baseThreadSchema, async ({ tx, args }) => {
558
+ for (const [, { threadIds }] of Object.entries(args.accounts)) {
559
+ for (const threadId of threadIds) {
560
+ await setSystemLabel(tx, zql, threadId, 'ARCHIVE');
561
+ }
562
+ }
563
+ }),
564
+ setFlagged: defineMutator(v.object({
565
+ accounts: accountsSchema,
566
+ flagged: v.nonOptional(v.boolean()),
567
+ }), async ({ tx, args }) => {
568
+ for (const [, { threadIds }] of Object.entries(args.accounts)) {
569
+ await Promise.all(threadIds.map(threadId => tx.mutate.thread.update({
570
+ flagged: args.flagged,
571
+ id: threadId,
572
+ })));
573
+ }
574
+ }),
575
+ setInbox: defineMutator(baseThreadSchema, async ({ tx, args }) => {
576
+ for (const [, { threadIds }] of Object.entries(args.accounts)) {
577
+ for (const threadId of threadIds) {
578
+ await setSystemLabel(tx, zql, threadId, 'INBOX');
579
+ }
580
+ }
581
+ }),
582
+ setSeen: defineMutator(v.object({
583
+ accounts: accountsSchema,
584
+ seen: v.boolean(),
585
+ }), async ({ tx, args }) => {
586
+ const allThreadIds = Object.values(args.accounts).flatMap(x => x.threadIds);
587
+ const threads = await tx.run(zql.thread.where('id', 'IN', allThreadIds));
588
+ const labelCounts = new Map();
589
+ for (const thread of threads) {
590
+ if (thread.seen !== args.seen) {
591
+ for (const labelId of threadsUtils.parseLabelIdList(thread.labelIdList)) {
592
+ labelCounts.set(labelId, (labelCounts.get(labelId) ?? 0) + 1);
593
+ }
594
+ }
595
+ }
596
+ if (labelCounts.size > 0) {
597
+ const labels = await tx.run(zql.accountLabel.where('id', 'IN', [...labelCounts.keys()]));
598
+ const delta = args.seen ? -1 : 1;
599
+ await Promise.all(labels
600
+ .filter(x => labelCounts.has(x.id))
601
+ .map(x => tx.mutate.accountLabel.update({
602
+ id: x.id,
603
+ unreadCount: Math.max(0, (x.unreadCount ?? 0) + delta * (labelCounts.get(x.id) ?? 0)),
604
+ })));
605
+ }
606
+ await Promise.all(allThreadIds.map(threadId => tx.mutate.thread.update({
607
+ id: threadId,
608
+ seen: args.seen,
609
+ })));
610
+ }),
611
+ setSpam: defineMutator(baseThreadSchema, async ({ tx, args }) => {
612
+ for (const [, { threadIds }] of Object.entries(args.accounts)) {
613
+ for (const threadId of threadIds) {
614
+ await setSystemLabel(tx, zql, threadId, 'SPAM');
615
+ }
616
+ }
617
+ }),
618
+ setTrash: defineMutator(baseThreadSchema, async ({ tx, args }) => {
619
+ for (const [, { threadIds }] of Object.entries(args.accounts)) {
620
+ for (const threadId of threadIds) {
621
+ await setSystemLabel(tx, zql, threadId, 'TRASH');
622
+ }
623
+ }
624
+ }),
625
+ },
626
+ user: {
627
+ deleteSettingsPushNotificationToken: defineMutator(v.object({
628
+ id: marcoSchemas.string.required(),
629
+ token: marcoSchemas.string.required(),
630
+ }), async ({ tx, args }) => {
631
+ await tx.mutate.userPushNotificationToken.delete({
632
+ id: args.id,
633
+ });
634
+ }),
635
+ setSettingsName: defineMutator(v.object({
636
+ id: marcoSchemas.string.required(),
637
+ name: marcoSchemas.string.nullable(),
638
+ }), async ({ tx, args }) => {
639
+ await tx.mutate.user.update({
640
+ id: args.id,
641
+ name: args.name,
642
+ });
643
+ }),
644
+ setSettingsPushNotificationToken: defineMutator(v.object({
645
+ id: marcoSchemas.string.required(),
646
+ pushNotificationToken: userPushNotificationTokenSchema,
647
+ }), async ({ tx, args }) => {
648
+ const existing = await tx.run(zql.userPushNotificationToken.where('userId', args.id).where('token', args.pushNotificationToken.token).one());
649
+ if (!existing) {
650
+ await tx.mutate.userPushNotificationToken.insert({
651
+ createdAt: args.pushNotificationToken.createdAt,
652
+ id: args.pushNotificationToken.id,
653
+ token: args.pushNotificationToken.token,
654
+ userId: args.id,
655
+ });
656
+ }
657
+ }),
658
+ },
659
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=mutators.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutators.test.d.ts","sourceRoot":"","sources":["../../src/zero/mutators.test.ts"],"names":[],"mappings":""}