@marcoappio/marco-config 2.0.476 → 2.0.478

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.
@@ -46,7 +46,7 @@ const configMap = {
46
46
  },
47
47
  img: {
48
48
  baseUrl: 'https://img.marcoapp.io',
49
- bucketName: 'UNKNOWN',
49
+ bucketName: 'marco-image-bucket-s3-qjw',
50
50
  },
51
51
  ws: {
52
52
  appId: 'marco-ws-production',
@@ -1 +1 @@
1
- {"version":3,"file":"threadMutators.d.ts","sourceRoot":"","sources":["../../../../src/zero/mutators/threadMutators/threadMutators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,KAAK,KAAK,CAAC,MAAM,SAAS,CAAA;AAEjC,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAC9E,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAiB,MAAM,qBAAqB,CAAA;AAEnF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AAC3E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAEhE,MAAM,MAAM,sBAAsB,GAAG;KAClC,CAAC,IAAI,MAAM,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAC1C,IAAI,EAAE,CAAC,CAAC,WAAW,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAC1D,OAAO,CAAC,IAAI,CAAC;CACnB,CAAA;AAKD,eAAO,MAAM,cAAc,OACrB,WAAW,CAAC,eAAe,CAAC,YACtB,MAAM,oBACE,eAAe,KAChC,OAAO,CAAC,kBAAkB,EAAE,CA0G9B,CAAA;AAED,eAAO,MAAM,oBAAoB,cACpB,QAAQ,GAAG,SAAS,cACnB,sBAAsB,KACjC,UAAU,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CA+OxC,CAAA"}
1
+ {"version":3,"file":"threadMutators.d.ts","sourceRoot":"","sources":["../../../../src/zero/mutators/threadMutators/threadMutators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,KAAK,KAAK,CAAC,MAAM,SAAS,CAAA;AAEjC,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAC9E,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAiB,MAAM,qBAAqB,CAAA;AAEnF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AAC3E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAEhE,MAAM,MAAM,sBAAsB,GAAG;KAClC,CAAC,IAAI,MAAM,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAC1C,IAAI,EAAE,CAAC,CAAC,WAAW,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAC1D,OAAO,CAAC,IAAI,CAAC;CACnB,CAAA;AAKD,eAAO,MAAM,cAAc,OACrB,WAAW,CAAC,eAAe,CAAC,YACtB,MAAM,oBACE,eAAe,KAChC,OAAO,CAAC,kBAAkB,EAAE,CA0G9B,CAAA;AAED,eAAO,MAAM,oBAAoB,cACpB,QAAQ,GAAG,SAAS,cACnB,sBAAsB,KACjC,UAAU,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAkQxC,CAAA"}
@@ -155,9 +155,24 @@ export const createThreadMutators = (_authData, callbacks) => ({
155
155
  },
156
156
  delete: async (tx, args) => {
157
157
  for (const threadId of args.threadIds) {
158
- await tx.mutate.thread.delete({
159
- id: threadId,
160
- });
158
+ const thread = await tx.query.thread.where('id', threadId).one().run();
159
+ if (thread) {
160
+ if (thread.seen === false) {
161
+ const labelIds = threadsUtils.parseLabelIdList(thread.labelIdList);
162
+ if (labelIds.length > 0) {
163
+ const labels = await tx.query.accountLabel.where('id', 'IN', labelIds).run();
164
+ for (const label of labels) {
165
+ await tx.mutate.accountLabel.update({
166
+ id: label.id,
167
+ unreadCount: Math.max(0, (label.unreadCount ?? 0) - 1),
168
+ });
169
+ }
170
+ }
171
+ }
172
+ await tx.mutate.thread.delete({
173
+ id: threadId,
174
+ });
175
+ }
161
176
  }
162
177
  callbacks?.delete?.(args);
163
178
  },
@@ -100,27 +100,105 @@ describe('threadMutators', () => {
100
100
  });
101
101
  });
102
102
  describe('delete', () => {
103
- it('deletes threads', async () => {
103
+ it('deletes threads and decrements unread counts for unread threads', async () => {
104
104
  const threadDelete = mock(async () => { });
105
+ const labelUpdate = mock(async () => { });
106
+ const threads = [
107
+ { id: 'test-thread-id-1', labelIdList: ' test-label-id-1 ', seen: false },
108
+ { id: 'test-thread-id-2', labelIdList: ' test-label-id-1 ', seen: true },
109
+ ];
110
+ const labels = [{ id: 'test-label-id-1', unreadCount: 5 }];
111
+ const runThread = mock(async (id) => threads.find(x => x.id === id));
112
+ const oneThread = mock(() => ({ run: () => runThread(whereThreadId) }));
113
+ let whereThreadId = '';
114
+ const whereThread = mock((_field, id) => {
115
+ whereThreadId = id;
116
+ return { one: oneThread };
117
+ });
118
+ const runLabels = mock(async () => labels);
119
+ const whereLabels = mock(() => ({ run: runLabels }));
105
120
  const transaction = {
106
121
  mutate: {
122
+ accountLabel: {
123
+ update: labelUpdate,
124
+ },
107
125
  thread: {
108
126
  delete: threadDelete,
109
127
  },
110
128
  },
111
- query: {},
129
+ query: {
130
+ accountLabel: {
131
+ where: whereLabels,
132
+ },
133
+ thread: {
134
+ where: whereThread,
135
+ },
136
+ },
112
137
  };
113
138
  const mutators = createMutators();
114
139
  await mutators.thread.delete(transaction, {
115
140
  threadIds: ['test-thread-id-1', 'test-thread-id-2'],
116
141
  });
117
142
  expect(threadDelete).toHaveBeenCalledTimes(2);
118
- expect(threadDelete).toHaveBeenCalledWith({
119
- id: 'test-thread-id-1',
143
+ expect(threadDelete).toHaveBeenCalledWith({ id: 'test-thread-id-1' });
144
+ expect(threadDelete).toHaveBeenCalledWith({ id: 'test-thread-id-2' });
145
+ expect(labelUpdate).toHaveBeenCalledTimes(1);
146
+ expect(labelUpdate).toHaveBeenCalledWith({
147
+ id: 'test-label-id-1',
148
+ unreadCount: 4,
149
+ });
150
+ });
151
+ it('does not update unread counts when deleting read threads', async () => {
152
+ const threadDelete = mock(async () => { });
153
+ const labelUpdate = mock(async () => { });
154
+ const thread = { id: 'test-thread-id-1', labelIdList: ' test-label-id-1 ', seen: true };
155
+ const runThread = mock(async () => thread);
156
+ const oneThread = mock(() => ({ run: runThread }));
157
+ const whereThread = mock(() => ({ one: oneThread }));
158
+ const transaction = {
159
+ mutate: {
160
+ accountLabel: {
161
+ update: labelUpdate,
162
+ },
163
+ thread: {
164
+ delete: threadDelete,
165
+ },
166
+ },
167
+ query: {
168
+ thread: {
169
+ where: whereThread,
170
+ },
171
+ },
172
+ };
173
+ const mutators = createMutators();
174
+ await mutators.thread.delete(transaction, {
175
+ threadIds: ['test-thread-id-1'],
120
176
  });
121
- expect(threadDelete).toHaveBeenCalledWith({
122
- id: 'test-thread-id-2',
177
+ expect(threadDelete).toHaveBeenCalledTimes(1);
178
+ expect(labelUpdate).not.toHaveBeenCalled();
179
+ });
180
+ it('handles non-existent threads gracefully', async () => {
181
+ const threadDelete = mock(async () => { });
182
+ const runThread = mock(async () => null);
183
+ const oneThread = mock(() => ({ run: runThread }));
184
+ const whereThread = mock(() => ({ one: oneThread }));
185
+ const transaction = {
186
+ mutate: {
187
+ thread: {
188
+ delete: threadDelete,
189
+ },
190
+ },
191
+ query: {
192
+ thread: {
193
+ where: whereThread,
194
+ },
195
+ },
196
+ };
197
+ const mutators = createMutators();
198
+ await mutators.thread.delete(transaction, {
199
+ threadIds: ['non-existent-thread'],
123
200
  });
201
+ expect(threadDelete).not.toHaveBeenCalled();
124
202
  });
125
203
  });
126
204
  describe('removeLabel', () => {
@@ -451,12 +529,12 @@ describe('threadMutators', () => {
451
529
  });
452
530
  });
453
531
  describe('setSeen', () => {
454
- it('sets thread seen status and updates unread count', async () => {
532
+ it('decrements unread count when marking unread threads as read', async () => {
455
533
  const threadUpdate = mock(async () => { });
456
534
  const labelUpdate = mock(async () => { });
457
535
  const threads = [
458
- { id: 'test-thread-id-1', labelIdList: ' test-inbox-label-id ' },
459
- { id: 'test-thread-id-2', labelIdList: ' test-inbox-label-id ' },
536
+ { id: 'test-thread-id-1', labelIdList: ' test-inbox-label-id ', seen: false },
537
+ { id: 'test-thread-id-2', labelIdList: ' test-inbox-label-id ', seen: false },
460
538
  ];
461
539
  const labels = [{ id: 'test-inbox-label-id', specialUse: 'INBOX', unreadCount: 5 }];
462
540
  const runThreads = mock(async () => threads);
@@ -487,23 +565,82 @@ describe('threadMutators', () => {
487
565
  threadIds: ['test-thread-id-1', 'test-thread-id-2'],
488
566
  });
489
567
  expect(threadUpdate).toHaveBeenCalledTimes(2);
490
- expect(threadUpdate).toHaveBeenCalledWith({
491
- id: 'test-thread-id-1',
492
- seen: true,
568
+ expect(labelUpdate).toHaveBeenCalledWith({
569
+ id: 'test-inbox-label-id',
570
+ unreadCount: 3,
493
571
  });
494
- expect(threadUpdate).toHaveBeenCalledWith({
495
- id: 'test-thread-id-2',
496
- seen: true,
572
+ });
573
+ it('increments unread count when marking read threads as unread', async () => {
574
+ const threadUpdate = mock(async () => { });
575
+ const labelUpdate = mock(async () => { });
576
+ const threads = [{ id: 'test-thread-id-1', labelIdList: ' test-inbox-label-id ', seen: true }];
577
+ const labels = [{ id: 'test-inbox-label-id', specialUse: 'INBOX', unreadCount: 5 }];
578
+ const runThreads = mock(async () => threads);
579
+ const whereThread = mock(() => ({ run: runThreads }));
580
+ const runLabels = mock(async () => labels);
581
+ const whereLabel = mock(() => ({ run: runLabels }));
582
+ const transaction = {
583
+ mutate: {
584
+ accountLabel: {
585
+ update: labelUpdate,
586
+ },
587
+ thread: {
588
+ update: threadUpdate,
589
+ },
590
+ },
591
+ query: {
592
+ accountLabel: {
593
+ where: whereLabel,
594
+ },
595
+ thread: {
596
+ where: whereThread,
597
+ },
598
+ },
599
+ };
600
+ const mutators = createMutators();
601
+ await mutators.thread.setSeen(transaction, {
602
+ seen: false,
603
+ threadIds: ['test-thread-id-1'],
497
604
  });
605
+ expect(threadUpdate).toHaveBeenCalledTimes(1);
498
606
  expect(labelUpdate).toHaveBeenCalledWith({
499
607
  id: 'test-inbox-label-id',
500
- unreadCount: 3,
608
+ unreadCount: 6,
501
609
  });
502
610
  });
503
611
  it('skips label update when threads have no labels', async () => {
504
612
  const threadUpdate = mock(async () => { });
505
613
  const labelUpdate = mock(async () => { });
506
- const threads = [{ id: 'test-thread-id-1', labelIdList: '' }];
614
+ const threads = [{ id: 'test-thread-id-1', labelIdList: '', seen: false }];
615
+ const runThreads = mock(async () => threads);
616
+ const whereThread = mock(() => ({ run: runThreads }));
617
+ const transaction = {
618
+ mutate: {
619
+ accountLabel: {
620
+ update: labelUpdate,
621
+ },
622
+ thread: {
623
+ update: threadUpdate,
624
+ },
625
+ },
626
+ query: {
627
+ thread: {
628
+ where: whereThread,
629
+ },
630
+ },
631
+ };
632
+ const mutators = createMutators();
633
+ await mutators.thread.setSeen(transaction, {
634
+ seen: true,
635
+ threadIds: ['test-thread-id-1'],
636
+ });
637
+ expect(threadUpdate).toHaveBeenCalledTimes(1);
638
+ expect(labelUpdate).not.toHaveBeenCalled();
639
+ });
640
+ it('skips already-read threads when marking as read', async () => {
641
+ const threadUpdate = mock(async () => { });
642
+ const labelUpdate = mock(async () => { });
643
+ const threads = [{ id: 'test-thread-id-1', labelIdList: ' test-inbox-label-id ', seen: true }];
507
644
  const runThreads = mock(async () => threads);
508
645
  const whereThread = mock(() => ({ run: runThreads }));
509
646
  const transaction = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marcoappio/marco-config",
3
- "version": "2.0.476",
3
+ "version": "2.0.478",
4
4
  "author": "team@marcoapp.io",
5
5
  "main": "dist/index.js",
6
6
  "repository": "git@github.com:marcoappio/marco-config.git",