@remit/drizzle-service 0.0.110 → 1.0.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.
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/repos/calendar-put.suite.ts +5 -2
- package/src/repos/calendar-store.ts +45 -15
- package/src/repos/calendar-task.ts +103 -0
- package/src/repos/i4-outbox-message.test.ts +2 -1
- package/src/repos/i4-outbox-message.ts +49 -18
- package/src/repos/outbox-scheduling-part.ts +68 -0
- package/src/schema-sets/app.ts +1 -0
- package/src/schema-sets/mail.ts +1 -0
- package/src/schema.ts +2 -0
- package/src/sqlite-repositories.ts +5 -1
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -33,6 +33,7 @@ export { CalendarFeedTokenRepo } from "./repos/calendar-feed-token.js";
|
|
|
33
33
|
export { CalendarObjectRepo } from "./repos/calendar-object.js";
|
|
34
34
|
export { DrizzleCalendarStore } from "./repos/calendar-store.js";
|
|
35
35
|
export { CalendarSuggestionRepo } from "./repos/calendar-suggestion.js";
|
|
36
|
+
export { CalendarTaskRepo } from "./repos/calendar-task.js";
|
|
36
37
|
export {
|
|
37
38
|
type CascadeDeleteLogger,
|
|
38
39
|
type CascadeDeleter,
|
|
@@ -78,6 +79,7 @@ export {
|
|
|
78
79
|
type MessageObjectStore,
|
|
79
80
|
messageObjectsInMemory,
|
|
80
81
|
} from "./repos/message-objects.js";
|
|
82
|
+
export { OutboxSchedulingPartRepo } from "./repos/outbox-scheduling-part.js";
|
|
81
83
|
export { QuarantineRepo } from "./repos/quarantine.js";
|
|
82
84
|
export { SyncWarningRepo } from "./repos/sync-warning.js";
|
|
83
85
|
export { DrizzleThreadMessageRepository } from "./repos/thread-message.js";
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
putCalendarObject,
|
|
7
7
|
} from "@remit/calendar-service";
|
|
8
8
|
import type {
|
|
9
|
+
CalendarCommitReport,
|
|
9
10
|
CalendarRepositories,
|
|
10
11
|
CalendarWrite,
|
|
11
12
|
ICalendarStore,
|
|
@@ -49,7 +50,9 @@ class FailingLastWriteStore implements ICalendarStore {
|
|
|
49
50
|
return this.inner.repos;
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
async commit(
|
|
53
|
+
async commit(
|
|
54
|
+
writes: readonly CalendarWrite[],
|
|
55
|
+
): Promise<CalendarCommitReport> {
|
|
53
56
|
const orphan = await prepareCalendarObject(
|
|
54
57
|
{ timezone: "" },
|
|
55
58
|
{
|
|
@@ -60,7 +63,7 @@ class FailingLastWriteStore implements ICalendarStore {
|
|
|
60
63
|
},
|
|
61
64
|
);
|
|
62
65
|
assert.ok(orphan.ok);
|
|
63
|
-
|
|
66
|
+
return this.inner.commit([...writes, orphan.value]);
|
|
64
67
|
}
|
|
65
68
|
}
|
|
66
69
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
CalendarCommitReport,
|
|
2
3
|
CalendarRepositories,
|
|
3
4
|
CalendarWrite,
|
|
4
5
|
ICalendarStore,
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
calendarFeedTokenTable,
|
|
16
17
|
calendarObjectTable,
|
|
17
18
|
calendarTable,
|
|
19
|
+
calendarTaskTable,
|
|
18
20
|
} from "../schema.js";
|
|
19
21
|
import { CalendarCollectionRepo } from "./calendar-collection.js";
|
|
20
22
|
import { CalendarEventIndexRepo } from "./calendar-event-index.js";
|
|
@@ -55,10 +57,30 @@ export class DrizzleCalendarStore implements ICalendarStore {
|
|
|
55
57
|
};
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
async commit(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
async commit(
|
|
61
|
+
writes: readonly CalendarWrite[],
|
|
62
|
+
): Promise<CalendarCommitReport> {
|
|
63
|
+
const items: SqliteBatchItem[] = [];
|
|
64
|
+
const reprojections: { at: number; calendarObjectId: string }[] = [];
|
|
65
|
+
for (const write of writes.filter(isBatchWrite)) {
|
|
66
|
+
items.push(...this.statements(write));
|
|
67
|
+
if (write.kind === "ReprojectObject") {
|
|
68
|
+
reprojections.push({
|
|
69
|
+
at: items.length - 1,
|
|
70
|
+
calendarObjectId: deriveCalendarObjectId(
|
|
71
|
+
write.object.calendarId,
|
|
72
|
+
write.object.resourceName,
|
|
73
|
+
),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const results: readonly unknown[] = await this.batch(items);
|
|
78
|
+
const staleReprojections = reprojections
|
|
79
|
+
.filter(({ at }) => {
|
|
80
|
+
const written = results[at];
|
|
81
|
+
return Array.isArray(written) && written.length === 0;
|
|
82
|
+
})
|
|
83
|
+
.map(({ calendarObjectId }) => calendarObjectId);
|
|
62
84
|
for (const write of writes.filter(isSettlement)) {
|
|
63
85
|
await this.repos.calendarSuggestion.settle(
|
|
64
86
|
write.accountConfigId,
|
|
@@ -66,6 +88,7 @@ export class DrizzleCalendarStore implements ICalendarStore {
|
|
|
66
88
|
write.settle,
|
|
67
89
|
);
|
|
68
90
|
}
|
|
91
|
+
return { staleReprojections };
|
|
69
92
|
}
|
|
70
93
|
|
|
71
94
|
private collection(accountConfigId: string, calendarId: string) {
|
|
@@ -167,6 +190,9 @@ export class DrizzleCalendarStore implements ICalendarStore {
|
|
|
167
190
|
);
|
|
168
191
|
// Every statement reads the object it rewrites at the version the
|
|
169
192
|
// caller read, so a resource edited or deleted since writes nothing.
|
|
193
|
+
// The object's own update runs last, so the occurrence statements still
|
|
194
|
+
// see that version, and it returns the row it wrote, so the commit can
|
|
195
|
+
// tell a stale read from a written one.
|
|
170
196
|
const asRead = and(
|
|
171
197
|
eq(calendarObjectTable.calendarObjectId, calendarObjectId),
|
|
172
198
|
eq(calendarObjectTable.etag, write.readEtag),
|
|
@@ -180,17 +206,6 @@ export class DrizzleCalendarStore implements ICalendarStore {
|
|
|
180
206
|
const value = <T>(field: T, name: string) => sql<T>`${field}`.as(name);
|
|
181
207
|
return [
|
|
182
208
|
this.bump(write.accountConfigId, calendarId),
|
|
183
|
-
this.db
|
|
184
|
-
.update(calendarObjectTable)
|
|
185
|
-
.set({
|
|
186
|
-
...write.object,
|
|
187
|
-
syncSequence: this.bumpedSequence(
|
|
188
|
-
write.accountConfigId,
|
|
189
|
-
calendarId,
|
|
190
|
-
),
|
|
191
|
-
updatedAt: now,
|
|
192
|
-
})
|
|
193
|
-
.where(asRead),
|
|
194
209
|
this.db
|
|
195
210
|
.delete(calendarEventIndexTable)
|
|
196
211
|
.where(
|
|
@@ -223,6 +238,18 @@ export class DrizzleCalendarStore implements ICalendarStore {
|
|
|
223
238
|
.where(asRead),
|
|
224
239
|
),
|
|
225
240
|
),
|
|
241
|
+
this.db
|
|
242
|
+
.update(calendarObjectTable)
|
|
243
|
+
.set({
|
|
244
|
+
...write.object,
|
|
245
|
+
syncSequence: this.bumpedSequence(
|
|
246
|
+
write.accountConfigId,
|
|
247
|
+
calendarId,
|
|
248
|
+
),
|
|
249
|
+
updatedAt: now,
|
|
250
|
+
})
|
|
251
|
+
.where(asRead)
|
|
252
|
+
.returning({ id: calendarObjectTable.calendarObjectId }),
|
|
226
253
|
];
|
|
227
254
|
}
|
|
228
255
|
case "DeleteObject":
|
|
@@ -250,6 +277,9 @@ export class DrizzleCalendarStore implements ICalendarStore {
|
|
|
250
277
|
];
|
|
251
278
|
case "DeleteCollection":
|
|
252
279
|
return [
|
|
280
|
+
this.db
|
|
281
|
+
.delete(calendarTaskTable)
|
|
282
|
+
.where(eq(calendarTaskTable.calendarId, write.calendarId)),
|
|
253
283
|
this.db
|
|
254
284
|
.delete(calendarEventIndexTable)
|
|
255
285
|
.where(eq(calendarEventIndexTable.calendarId, write.calendarId)),
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CalendarTaskItem,
|
|
3
|
+
ICalendarTaskRepository,
|
|
4
|
+
PutCalendarTaskInput,
|
|
5
|
+
} from "@remit/data-ports";
|
|
6
|
+
import { deriveCalendarTaskId } from "@remit/data-ports/id";
|
|
7
|
+
import { and, asc, eq, gte, lt } from "drizzle-orm";
|
|
8
|
+
import type { RepositoryDb } from "../db.js";
|
|
9
|
+
import { calendarTaskTable } from "../schema.js";
|
|
10
|
+
|
|
11
|
+
type DB = RepositoryDb<Record<string, unknown>>;
|
|
12
|
+
|
|
13
|
+
const rowToTask = (
|
|
14
|
+
row: typeof calendarTaskTable.$inferSelect,
|
|
15
|
+
): CalendarTaskItem => ({
|
|
16
|
+
calendarTaskId: row.calendarTaskId,
|
|
17
|
+
calendarId: row.calendarId,
|
|
18
|
+
resourceName: row.resourceName,
|
|
19
|
+
icalUid: row.icalUid,
|
|
20
|
+
icalData: row.icalData,
|
|
21
|
+
etag: row.etag,
|
|
22
|
+
summary: row.summary,
|
|
23
|
+
description: row.description,
|
|
24
|
+
due: row.due,
|
|
25
|
+
dueAt: row.dueAt,
|
|
26
|
+
allDay: row.allDay,
|
|
27
|
+
completed: row.completed,
|
|
28
|
+
createdAt: row.createdAt,
|
|
29
|
+
updatedAt: row.updatedAt,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export class CalendarTaskRepo implements ICalendarTaskRepository {
|
|
33
|
+
constructor(private db: DB) {}
|
|
34
|
+
|
|
35
|
+
async put(input: PutCalendarTaskInput): Promise<CalendarTaskItem> {
|
|
36
|
+
const now = Date.now();
|
|
37
|
+
const calendarTaskId = deriveCalendarTaskId(
|
|
38
|
+
input.calendarId,
|
|
39
|
+
input.resourceName,
|
|
40
|
+
);
|
|
41
|
+
const [row] = await this.db
|
|
42
|
+
.insert(calendarTaskTable)
|
|
43
|
+
.values({ ...input, calendarTaskId, createdAt: now, updatedAt: now })
|
|
44
|
+
.onConflictDoUpdate({
|
|
45
|
+
target: calendarTaskTable.calendarTaskId,
|
|
46
|
+
set: { ...input, updatedAt: now },
|
|
47
|
+
})
|
|
48
|
+
.returning();
|
|
49
|
+
return rowToTask(row);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async find(
|
|
53
|
+
calendarId: string,
|
|
54
|
+
calendarTaskId: string,
|
|
55
|
+
): Promise<CalendarTaskItem | null> {
|
|
56
|
+
const [row] = await this.db
|
|
57
|
+
.select()
|
|
58
|
+
.from(calendarTaskTable)
|
|
59
|
+
.where(
|
|
60
|
+
and(
|
|
61
|
+
eq(calendarTaskTable.calendarId, calendarId),
|
|
62
|
+
eq(calendarTaskTable.calendarTaskId, calendarTaskId),
|
|
63
|
+
),
|
|
64
|
+
);
|
|
65
|
+
return row ? rowToTask(row) : null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async delete(calendarId: string, calendarTaskId: string): Promise<void> {
|
|
69
|
+
await this.db
|
|
70
|
+
.delete(calendarTaskTable)
|
|
71
|
+
.where(
|
|
72
|
+
and(
|
|
73
|
+
eq(calendarTaskTable.calendarId, calendarId),
|
|
74
|
+
eq(calendarTaskTable.calendarTaskId, calendarTaskId),
|
|
75
|
+
),
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async listByDueRange(
|
|
80
|
+
calendarId: string,
|
|
81
|
+
fromAt: string,
|
|
82
|
+
toAt: string,
|
|
83
|
+
): Promise<CalendarTaskItem[]> {
|
|
84
|
+
const rows = await this.db
|
|
85
|
+
.select()
|
|
86
|
+
.from(calendarTaskTable)
|
|
87
|
+
.where(
|
|
88
|
+
and(
|
|
89
|
+
eq(calendarTaskTable.calendarId, calendarId),
|
|
90
|
+
gte(calendarTaskTable.dueAt, fromAt),
|
|
91
|
+
lt(calendarTaskTable.dueAt, toAt),
|
|
92
|
+
),
|
|
93
|
+
)
|
|
94
|
+
.orderBy(asc(calendarTaskTable.dueAt));
|
|
95
|
+
return rows.map(rowToTask);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async deleteByCalendar(calendarId: string): Promise<void> {
|
|
99
|
+
await this.db
|
|
100
|
+
.delete(calendarTaskTable)
|
|
101
|
+
.where(eq(calendarTaskTable.calendarId, calendarId));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { after, before, describe, test } from "node:test";
|
|
3
|
+
import { syncBatch } from "../batch.js";
|
|
3
4
|
import { ForbiddenError, NotFoundError } from "../error.js";
|
|
4
5
|
import { createTestDb, randomId, type TestDb } from "../test-db.js";
|
|
5
6
|
import { OutboxMessageRepo } from "./i4-outbox-message.js";
|
|
@@ -22,7 +23,7 @@ describe("OutboxMessageRepo", () => {
|
|
|
22
23
|
|
|
23
24
|
before(async () => {
|
|
24
25
|
({ db, close } = await createTestDb());
|
|
25
|
-
repo = new OutboxMessageRepo(db as never);
|
|
26
|
+
repo = new OutboxMessageRepo(db as never, syncBatch(db));
|
|
26
27
|
});
|
|
27
28
|
|
|
28
29
|
after(async () => {
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
CreateOutboxMessageInput,
|
|
3
|
+
CreateOutboxSchedulingPartInput,
|
|
3
4
|
IOutboxMessageRepository,
|
|
4
5
|
OutboxMessageItem,
|
|
5
6
|
ResultList,
|
|
6
7
|
UpdateOutboxMessageInput,
|
|
7
8
|
} from "@remit/data-ports";
|
|
9
|
+
import { base36uuid } from "@remit/data-ports/id";
|
|
8
10
|
import { and, desc, eq, lt, or } from "drizzle-orm";
|
|
11
|
+
import type { WriteBatch } from "../batch.js";
|
|
9
12
|
import type { RepositoryDb } from "../db.js";
|
|
10
13
|
import { ForbiddenError, NotFoundError } from "../error.js";
|
|
11
14
|
import { decodeToken, resultList } from "../pagination.js";
|
|
12
15
|
import { outboxMessageTable } from "../schema/i4-outbox-message.js";
|
|
16
|
+
import { outboxSchedulingPartTable } from "../schema.js";
|
|
13
17
|
import { inList } from "./in-list.js";
|
|
14
18
|
|
|
15
19
|
type DB = RepositoryDb<Record<string, unknown>>;
|
|
@@ -45,13 +49,21 @@ function rowToOutboxMessage(
|
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
export class OutboxMessageRepo implements IOutboxMessageRepository {
|
|
48
|
-
constructor(
|
|
52
|
+
constructor(
|
|
53
|
+
private db: DB,
|
|
54
|
+
private batch: WriteBatch,
|
|
55
|
+
) {}
|
|
49
56
|
|
|
50
|
-
async create(
|
|
57
|
+
async create(
|
|
58
|
+
input: CreateOutboxMessageInput,
|
|
59
|
+
schedulingPart?: CreateOutboxSchedulingPartInput,
|
|
60
|
+
): Promise<OutboxMessageItem> {
|
|
51
61
|
const now = Date.now();
|
|
52
|
-
const
|
|
62
|
+
const outboxMessageId = base36uuid();
|
|
63
|
+
const insert = this.db
|
|
53
64
|
.insert(outboxMessageTable)
|
|
54
65
|
.values({
|
|
66
|
+
outboxMessageId,
|
|
55
67
|
accountId: input.accountId,
|
|
56
68
|
accountConfigId: input.accountConfigId,
|
|
57
69
|
fromAddress: input.fromAddress,
|
|
@@ -75,6 +87,21 @@ export class OutboxMessageRepo implements IOutboxMessageRepository {
|
|
|
75
87
|
updatedAt: now,
|
|
76
88
|
})
|
|
77
89
|
.returning();
|
|
90
|
+
if (!schedulingPart) {
|
|
91
|
+
const [row] = await insert;
|
|
92
|
+
return rowToOutboxMessage(row);
|
|
93
|
+
}
|
|
94
|
+
const [rows] = await this.batch([
|
|
95
|
+
insert,
|
|
96
|
+
this.db.insert(outboxSchedulingPartTable).values({
|
|
97
|
+
...schedulingPart,
|
|
98
|
+
outboxMessageId,
|
|
99
|
+
accountConfigId: input.accountConfigId,
|
|
100
|
+
createdAt: now,
|
|
101
|
+
updatedAt: now,
|
|
102
|
+
}),
|
|
103
|
+
]);
|
|
104
|
+
const [row] = rows as (typeof outboxMessageTable.$inferSelect)[];
|
|
78
105
|
return rowToOutboxMessage(row);
|
|
79
106
|
}
|
|
80
107
|
|
|
@@ -241,18 +268,12 @@ export class OutboxMessageRepo implements IOutboxMessageRepository {
|
|
|
241
268
|
return rowToOutboxMessage(row);
|
|
242
269
|
}
|
|
243
270
|
|
|
271
|
+
/** The row and its scheduling part go together, or neither does. */
|
|
244
272
|
async delete(
|
|
245
273
|
accountConfigId: string,
|
|
246
274
|
outboxMessageId: string,
|
|
247
275
|
): Promise<void> {
|
|
248
|
-
await this.
|
|
249
|
-
.delete(outboxMessageTable)
|
|
250
|
-
.where(
|
|
251
|
-
and(
|
|
252
|
-
eq(outboxMessageTable.accountConfigId, accountConfigId),
|
|
253
|
-
eq(outboxMessageTable.outboxMessageId, outboxMessageId),
|
|
254
|
-
),
|
|
255
|
-
);
|
|
276
|
+
await this.deleteMany(accountConfigId, [outboxMessageId]);
|
|
256
277
|
}
|
|
257
278
|
|
|
258
279
|
async deleteMany(
|
|
@@ -260,14 +281,24 @@ export class OutboxMessageRepo implements IOutboxMessageRepository {
|
|
|
260
281
|
outboxMessageIds: string[],
|
|
261
282
|
): Promise<void> {
|
|
262
283
|
if (outboxMessageIds.length === 0) return;
|
|
263
|
-
await this.
|
|
264
|
-
.
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
284
|
+
await this.batch([
|
|
285
|
+
this.db
|
|
286
|
+
.delete(outboxMessageTable)
|
|
287
|
+
.where(
|
|
288
|
+
and(
|
|
289
|
+
eq(outboxMessageTable.accountConfigId, accountConfigId),
|
|
290
|
+
inList(outboxMessageTable.outboxMessageId, outboxMessageIds),
|
|
291
|
+
),
|
|
269
292
|
),
|
|
270
|
-
|
|
293
|
+
this.db
|
|
294
|
+
.delete(outboxSchedulingPartTable)
|
|
295
|
+
.where(
|
|
296
|
+
and(
|
|
297
|
+
eq(outboxSchedulingPartTable.accountConfigId, accountConfigId),
|
|
298
|
+
inList(outboxSchedulingPartTable.outboxMessageId, outboxMessageIds),
|
|
299
|
+
),
|
|
300
|
+
),
|
|
301
|
+
]);
|
|
271
302
|
}
|
|
272
303
|
|
|
273
304
|
async listByAccount(
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
IOutboxSchedulingPartRepository,
|
|
3
|
+
OutboxSchedulingPartItem,
|
|
4
|
+
} from "@remit/data-ports";
|
|
5
|
+
import { and, asc, eq } from "drizzle-orm";
|
|
6
|
+
import type { RepositoryDb } from "../db.js";
|
|
7
|
+
import { outboxMessageTable } from "../schema/i4-outbox-message.js";
|
|
8
|
+
import { outboxSchedulingPartTable } from "../schema.js";
|
|
9
|
+
|
|
10
|
+
type DB = RepositoryDb<Record<string, unknown>>;
|
|
11
|
+
|
|
12
|
+
const rowToPart = (
|
|
13
|
+
row: typeof outboxSchedulingPartTable.$inferSelect,
|
|
14
|
+
): OutboxSchedulingPartItem => ({
|
|
15
|
+
outboxMessageId: row.outboxMessageId,
|
|
16
|
+
accountConfigId: row.accountConfigId,
|
|
17
|
+
calendarObjectId: row.calendarObjectId,
|
|
18
|
+
recipient: row.recipient,
|
|
19
|
+
method: row.method,
|
|
20
|
+
sequence: row.sequence,
|
|
21
|
+
icalData: row.icalData,
|
|
22
|
+
createdAt: row.createdAt,
|
|
23
|
+
updatedAt: row.updatedAt,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export class OutboxSchedulingPartRepo
|
|
27
|
+
implements IOutboxSchedulingPartRepository
|
|
28
|
+
{
|
|
29
|
+
constructor(private db: DB) {}
|
|
30
|
+
|
|
31
|
+
async find(
|
|
32
|
+
outboxMessageId: string,
|
|
33
|
+
): Promise<OutboxSchedulingPartItem | null> {
|
|
34
|
+
const [row] = await this.db
|
|
35
|
+
.select()
|
|
36
|
+
.from(outboxSchedulingPartTable)
|
|
37
|
+
.where(eq(outboxSchedulingPartTable.outboxMessageId, outboxMessageId));
|
|
38
|
+
return row ? rowToPart(row) : null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Joined to the outbox so a part whose message left the outbox by a path
|
|
43
|
+
* that did not take the part with it is never reported as still in flight.
|
|
44
|
+
*/
|
|
45
|
+
async listByCalendarObject(
|
|
46
|
+
accountConfigId: string,
|
|
47
|
+
calendarObjectId: string,
|
|
48
|
+
): Promise<OutboxSchedulingPartItem[]> {
|
|
49
|
+
const rows = await this.db
|
|
50
|
+
.select({ part: outboxSchedulingPartTable })
|
|
51
|
+
.from(outboxSchedulingPartTable)
|
|
52
|
+
.innerJoin(
|
|
53
|
+
outboxMessageTable,
|
|
54
|
+
eq(
|
|
55
|
+
outboxMessageTable.outboxMessageId,
|
|
56
|
+
outboxSchedulingPartTable.outboxMessageId,
|
|
57
|
+
),
|
|
58
|
+
)
|
|
59
|
+
.where(
|
|
60
|
+
and(
|
|
61
|
+
eq(outboxSchedulingPartTable.accountConfigId, accountConfigId),
|
|
62
|
+
eq(outboxSchedulingPartTable.calendarObjectId, calendarObjectId),
|
|
63
|
+
),
|
|
64
|
+
)
|
|
65
|
+
.orderBy(asc(outboxSchedulingPartTable.createdAt));
|
|
66
|
+
return rows.map(({ part }) => rowToPart(part));
|
|
67
|
+
}
|
|
68
|
+
}
|
package/src/schema-sets/app.ts
CHANGED
package/src/schema-sets/mail.ts
CHANGED
package/src/schema.ts
CHANGED
|
@@ -11,6 +11,8 @@ export const calendarTable = entities.calendarCollections;
|
|
|
11
11
|
export const calendarObjectTable = entities.calendarObjects;
|
|
12
12
|
export const calendarEventIndexTable = entities.calendarEventIndexes;
|
|
13
13
|
export const calendarFeedTokenTable = entities.calendarFeedTokens;
|
|
14
|
+
export const calendarTaskTable = entities.calendarTasks;
|
|
15
|
+
export const outboxSchedulingPartTable = entities.outboxSchedulingParts;
|
|
14
16
|
export const calendarSuggestionTable = entities.calendarSuggestions;
|
|
15
17
|
export const filterTable = entities.filters;
|
|
16
18
|
export const labelTable = entities.labels;
|
|
@@ -10,6 +10,7 @@ import { CalendarFeedTokenRepo } from "./repos/calendar-feed-token.js";
|
|
|
10
10
|
import { CalendarObjectRepo } from "./repos/calendar-object.js";
|
|
11
11
|
import { DrizzleCalendarStore } from "./repos/calendar-store.js";
|
|
12
12
|
import { CalendarSuggestionRepo } from "./repos/calendar-suggestion.js";
|
|
13
|
+
import { CalendarTaskRepo } from "./repos/calendar-task.js";
|
|
13
14
|
import { DrizzleEnvelopeRepository } from "./repos/envelope.js";
|
|
14
15
|
import { FilterRepo } from "./repos/filter.js";
|
|
15
16
|
import { AccountRepo } from "./repos/i4-account.js";
|
|
@@ -35,6 +36,7 @@ import {
|
|
|
35
36
|
type MessageObjectStore,
|
|
36
37
|
MessageObjects,
|
|
37
38
|
} from "./repos/message-objects.js";
|
|
39
|
+
import { OutboxSchedulingPartRepo } from "./repos/outbox-scheduling-part.js";
|
|
38
40
|
import { QuarantineRepo } from "./repos/quarantine.js";
|
|
39
41
|
import { SyncWarningRepo } from "./repos/sync-warning.js";
|
|
40
42
|
import { DrizzleThreadMessageRepository } from "./repos/thread-message.js";
|
|
@@ -70,7 +72,8 @@ export const composeSqliteRepositories = (
|
|
|
70
72
|
mailboxLock: new MailboxLockRepo(mail.db),
|
|
71
73
|
message,
|
|
72
74
|
messageFlag: new DrizzleMessageFlagRepository(mail.db),
|
|
73
|
-
outboxMessage: new OutboxMessageRepo(mail.db),
|
|
75
|
+
outboxMessage: new OutboxMessageRepo(mail.db, mail.batch),
|
|
76
|
+
outboxSchedulingPart: new OutboxSchedulingPartRepo(mail.db),
|
|
74
77
|
outboxAttachment: new OutboxAttachmentRepo(mail),
|
|
75
78
|
threadMessage: new DrizzleThreadMessageRepository(mail, searchIndex),
|
|
76
79
|
envelope: new DrizzleEnvelopeRepository(mail),
|
|
@@ -89,6 +92,7 @@ export const composeSqliteRepositories = (
|
|
|
89
92
|
calendarObject: new CalendarObjectRepo(app.db),
|
|
90
93
|
calendarEventIndex: new CalendarEventIndexRepo(app),
|
|
91
94
|
calendarFeedToken: new CalendarFeedTokenRepo(app.db),
|
|
95
|
+
calendarTask: new CalendarTaskRepo(app.db),
|
|
92
96
|
calendarSuggestion,
|
|
93
97
|
calendarStore: new DrizzleCalendarStore(app, calendarSuggestion),
|
|
94
98
|
};
|