@headless-lms/adapter-db 0.3.0 → 0.5.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/dist/client.d.ts +8 -2
- package/dist/client.js +10 -2
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +10 -4
- package/dist/index.js +9 -3
- package/dist/repositories/admin.d.ts +12 -4
- package/dist/repositories/admin.js +165 -23
- package/dist/repositories/admin.js.map +1 -1
- package/dist/repositories/assets.d.ts +2 -2
- package/dist/repositories/assets.js +11 -5
- package/dist/repositories/assets.js.map +1 -1
- package/dist/repositories/automations.d.ts +0 -1
- package/dist/repositories/automations.js +2 -18
- package/dist/repositories/automations.js.map +1 -1
- package/dist/repositories/chats.d.ts +14 -5
- package/dist/repositories/chats.js +194 -85
- package/dist/repositories/chats.js.map +1 -1
- package/dist/repositories/content.d.ts +24 -7
- package/dist/repositories/content.js +229 -48
- package/dist/repositories/content.js.map +1 -1
- package/dist/repositories/credentials.js +1 -1
- package/dist/repositories/devices.d.ts +17 -0
- package/dist/repositories/devices.js +75 -0
- package/dist/repositories/devices.js.map +1 -0
- package/dist/repositories/digest-runs.d.ts +14 -0
- package/dist/repositories/digest-runs.js +39 -0
- package/dist/repositories/digest-runs.js.map +1 -0
- package/dist/repositories/discussion.d.ts +7 -2
- package/dist/repositories/discussion.js +18 -7
- package/dist/repositories/discussion.js.map +1 -1
- package/dist/repositories/entitlements.d.ts +11 -9
- package/dist/repositories/entitlements.js +56 -59
- package/dist/repositories/entitlements.js.map +1 -1
- package/dist/repositories/event-reports.d.ts +16 -0
- package/dist/repositories/event-reports.js +199 -0
- package/dist/repositories/event-reports.js.map +1 -0
- package/dist/repositories/grant-covers.d.ts +4 -3
- package/dist/repositories/grant-covers.js +7 -4
- package/dist/repositories/grant-covers.js.map +1 -1
- package/dist/repositories/identity.js +1 -1
- package/dist/repositories/inserted-row.d.ts +5 -0
- package/dist/repositories/inserted-row.js +7 -0
- package/dist/repositories/inserted-row.js.map +1 -0
- package/dist/repositories/integrations.js +1 -1
- package/dist/repositories/member.d.ts +12 -4
- package/dist/repositories/member.js +19 -7
- package/dist/repositories/member.js.map +1 -1
- package/dist/repositories/members.d.ts +2 -5
- package/dist/repositories/members.js +39 -94
- package/dist/repositories/members.js.map +1 -1
- package/dist/repositories/mentions.d.ts +17 -0
- package/dist/repositories/mentions.js +55 -0
- package/dist/repositories/mentions.js.map +1 -0
- package/dist/repositories/notification-settings.d.ts +19 -0
- package/dist/repositories/notification-settings.js +67 -0
- package/dist/repositories/notification-settings.js.map +1 -0
- package/dist/repositories/notifications.d.ts +23 -16
- package/dist/repositories/notifications.js +152 -44
- package/dist/repositories/notifications.js.map +1 -1
- package/dist/repositories/org-user-profile.d.ts +0 -17
- package/dist/repositories/org-user-profile.js +0 -1
- package/dist/repositories/org-user-profile.js.map +1 -1
- package/dist/repositories/organizations.d.ts +4 -4
- package/dist/repositories/organizations.js +25 -47
- package/dist/repositories/organizations.js.map +1 -1
- package/dist/repositories/outbox.d.ts +5 -1
- package/dist/repositories/outbox.js +12 -3
- package/dist/repositories/outbox.js.map +1 -1
- package/dist/repositories/posts.d.ts +4 -8
- package/dist/repositories/posts.js +26 -29
- package/dist/repositories/posts.js.map +1 -1
- package/dist/repositories/progress.js +1 -1
- package/dist/repositories/roles.d.ts +35 -0
- package/dist/repositories/roles.js +244 -0
- package/dist/repositories/roles.js.map +1 -0
- package/dist/repositories/settings.js +1 -1
- package/dist/repositories/subscriptions.d.ts +18 -0
- package/dist/repositories/subscriptions.js +72 -0
- package/dist/repositories/subscriptions.js.map +1 -0
- package/dist/schema/assets.d.ts +17 -0
- package/dist/schema/assets.js +1 -0
- package/dist/schema/assets.js.map +1 -1
- package/dist/schema/automations.d.ts +524 -19
- package/dist/schema/automations.js +73 -7
- package/dist/schema/automations.js.map +1 -1
- package/dist/schema/content.d.ts +437 -3
- package/dist/schema/content.js +70 -3
- package/dist/schema/content.js.map +1 -1
- package/dist/schema/discussion.d.ts +295 -128
- package/dist/schema/discussion.js +63 -26
- package/dist/schema/discussion.js.map +1 -1
- package/dist/schema/identity.d.ts +109 -109
- package/dist/schema/identity.js +28 -70
- package/dist/schema/identity.js.map +1 -1
- package/dist/schema/index.d.ts +7 -6
- package/dist/schema/index.js +16 -7
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/organizations.d.ts +5 -22
- package/dist/schema/organizations.js +1 -13
- package/dist/schema/organizations.js.map +1 -1
- package/dist/schema/roles.d.ts +369 -0
- package/dist/schema/roles.js +71 -0
- package/dist/schema/roles.js.map +1 -0
- package/drizzle/0011_digest_runs.sql +8 -0
- package/drizzle/0012_subscriptions.sql +16 -0
- package/drizzle/0013_mentions.sql +10 -0
- package/drizzle/0014_notification_settings_devices.sql +36 -0
- package/drizzle/0015_automations_drop_source.sql +2 -0
- package/drizzle/0016_notifications_automations.sql +48 -0
- package/drizzle/0017_configurable_roles.sql +38 -0
- package/drizzle/0018_messages_client_id.sql +2 -0
- package/drizzle/0019_events.sql +44 -0
- package/drizzle/meta/0011_snapshot.json +8868 -0
- package/drizzle/meta/0012_snapshot.json +8873 -0
- package/drizzle/meta/0013_snapshot.json +8943 -0
- package/drizzle/meta/0014_snapshot.json +9305 -0
- package/drizzle/meta/0015_snapshot.json +9270 -0
- package/drizzle/meta/0016_snapshot.json +9230 -0
- package/drizzle/meta/0017_snapshot.json +9518 -0
- package/drizzle/meta/0018_snapshot.json +9557 -0
- package/drizzle/meta/0019_snapshot.json +9919 -0
- package/drizzle/meta/_journal.json +63 -0
- package/package.json +2 -2
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { activities, activityAssets, bundleItems, bundles, communities, contentItems, courses, downloadAssets, downloads, modules, spaceLinks, spaceTopics, spaces } from "../schema/content.js";
|
|
2
|
-
import { posts } from "../schema/discussion.js";
|
|
1
|
+
import { activities, activityAssets, bundleItems, bundles, communities, contentItems, courses, downloadAssets, downloads, eventAssets, events, modules, spaceLinks, spaceTopics, spaces } from "../schema/content.js";
|
|
3
2
|
import { settings } from "../schema/settings.js";
|
|
3
|
+
import { posts } from "../schema/discussion.js";
|
|
4
4
|
import { isUniqueViolation, pgErrorFields, translateDbErrors } from "./pg-errors.js";
|
|
5
5
|
import { deepMerge } from "./settings.js";
|
|
6
|
-
import {
|
|
6
|
+
import { noopLogger } from "@headless-lms/core/shared/logger";
|
|
7
|
+
import { and, asc, count, desc, eq, gt, ilike, inArray, lt, or, sql } from "drizzle-orm";
|
|
7
8
|
import { genId } from "@headless-lms/core/shared/id";
|
|
8
9
|
import { ConflictError, NotFoundError } from "@headless-lms/core/shared/errors";
|
|
9
|
-
import {
|
|
10
|
-
import { communitySettingsDefaults, courseSettingsDefaults, spaceSettingsDefaults } from "@headless-lms/core/schemas";
|
|
10
|
+
import { communitySettingsDefaults, courseSettingsDefaults, digestScheduleSchema, eventSettingsDefaults, spaceSettingsDefaults } from "@headless-lms/core/schemas";
|
|
11
11
|
//#region src/repositories/content.ts
|
|
12
12
|
const LIBRARY_ONLY = "An activity can only use ready files from the media library";
|
|
13
13
|
const MISSING_ASSET_DETAIL = /^Key \(org_id, asset_id\)=\((?:[^,]+), (.+?)\) is not present/;
|
|
@@ -21,16 +21,38 @@ function refusedLink(err) {
|
|
|
21
21
|
const SETTINGS_NAMESPACE = "content";
|
|
22
22
|
const courseSettingsJoin = and(eq(settings.orgId, courses.orgId), eq(settings.namespace, SETTINGS_NAMESPACE), eq(settings.scopeId, courses.id));
|
|
23
23
|
const communitySettingsJoin = and(eq(settings.orgId, communities.orgId), eq(settings.namespace, SETTINGS_NAMESPACE), eq(settings.scopeId, communities.id));
|
|
24
|
+
const eventSettingsJoin = and(eq(settings.orgId, events.orgId), eq(settings.namespace, SETTINGS_NAMESPACE), eq(settings.scopeId, events.id));
|
|
25
|
+
function toEvent(row, storedSettings) {
|
|
26
|
+
return {
|
|
27
|
+
...row,
|
|
28
|
+
status: row.status,
|
|
29
|
+
settings: {
|
|
30
|
+
...eventSettingsDefaults,
|
|
31
|
+
...storedSettings
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const eventSortColumns = {
|
|
36
|
+
startsAt: events.startsAt,
|
|
37
|
+
title: events.title
|
|
38
|
+
};
|
|
39
|
+
function storedDigest(value) {
|
|
40
|
+
const parsed = digestScheduleSchema.safeParse(value);
|
|
41
|
+
return parsed.success ? parsed.data : null;
|
|
42
|
+
}
|
|
24
43
|
function toCommunity(row, storedSettings) {
|
|
25
44
|
const raw = storedSettings?.dm;
|
|
26
45
|
const stored = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
27
46
|
return {
|
|
28
47
|
...row,
|
|
29
48
|
status: row.status,
|
|
30
|
-
settings: {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
49
|
+
settings: {
|
|
50
|
+
dm: {
|
|
51
|
+
...communitySettingsDefaults.dm,
|
|
52
|
+
...stored
|
|
53
|
+
},
|
|
54
|
+
digest: storedDigest(storedSettings?.digest)
|
|
55
|
+
}
|
|
34
56
|
};
|
|
35
57
|
}
|
|
36
58
|
function toSpace(row) {
|
|
@@ -99,8 +121,15 @@ var DrizzleContentRepository = class {
|
|
|
99
121
|
tx(fn) {
|
|
100
122
|
return this.db.transaction(fn);
|
|
101
123
|
}
|
|
102
|
-
async listCourses(orgId, query) {
|
|
124
|
+
async listCourses(orgId, query, ids) {
|
|
125
|
+
if (ids?.length === 0) return {
|
|
126
|
+
rows: [],
|
|
127
|
+
total: 0,
|
|
128
|
+
page: query.page,
|
|
129
|
+
pageSize: query.pageSize
|
|
130
|
+
};
|
|
103
131
|
const conditions = [eq(courses.orgId, orgId)];
|
|
132
|
+
if (ids) conditions.push(inArray(courses.id, ids));
|
|
104
133
|
if (query.status) conditions.push(eq(courses.status, query.status));
|
|
105
134
|
if (query.category) conditions.push(eq(courses.category, query.category));
|
|
106
135
|
const search = query.search?.trim();
|
|
@@ -173,27 +202,7 @@ var DrizzleContentRepository = class {
|
|
|
173
202
|
return this.findCourseById(orgId, id);
|
|
174
203
|
}
|
|
175
204
|
async patchCourseSettings(orgId, id, value) {
|
|
176
|
-
const
|
|
177
|
-
const merged = await this.tx(async (tx) => {
|
|
178
|
-
let [existing] = await tx.select().from(settings).where(key).for("update");
|
|
179
|
-
if (!existing) {
|
|
180
|
-
const [inserted] = await tx.insert(settings).values({
|
|
181
|
-
orgId,
|
|
182
|
-
namespace: SETTINGS_NAMESPACE,
|
|
183
|
-
scopeId: id,
|
|
184
|
-
value
|
|
185
|
-
}).onConflictDoNothing().returning();
|
|
186
|
-
if (inserted) return inserted.value;
|
|
187
|
-
[existing] = await tx.select().from(settings).where(key).for("update");
|
|
188
|
-
if (!existing) throw new Error("course settings patch: row vanished mid-transaction");
|
|
189
|
-
}
|
|
190
|
-
const [updated] = await tx.update(settings).set({
|
|
191
|
-
value: deepMerge(existing.value, value),
|
|
192
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
193
|
-
}).where(key).returning();
|
|
194
|
-
if (!updated) throw new Error("course settings patch returned no row");
|
|
195
|
-
return updated.value;
|
|
196
|
-
});
|
|
205
|
+
const merged = await this.patchSettings(orgId, id, value);
|
|
197
206
|
return {
|
|
198
207
|
...courseSettingsDefaults,
|
|
199
208
|
...merged
|
|
@@ -334,8 +343,15 @@ var DrizzleContentRepository = class {
|
|
|
334
343
|
return this.listModules(tx, orgId, courseId);
|
|
335
344
|
});
|
|
336
345
|
}
|
|
337
|
-
async listDownloads(orgId, query) {
|
|
346
|
+
async listDownloads(orgId, query, ids) {
|
|
347
|
+
if (ids?.length === 0) return {
|
|
348
|
+
rows: [],
|
|
349
|
+
total: 0,
|
|
350
|
+
page: query.page,
|
|
351
|
+
pageSize: query.pageSize
|
|
352
|
+
};
|
|
338
353
|
const conditions = [eq(downloads.orgId, orgId)];
|
|
354
|
+
if (ids) conditions.push(inArray(downloads.id, ids));
|
|
339
355
|
if (query.status) conditions.push(eq(downloads.status, query.status));
|
|
340
356
|
if (query.category) conditions.push(eq(downloads.category, query.category));
|
|
341
357
|
const search = query.search?.trim();
|
|
@@ -444,6 +460,144 @@ var DrizzleContentRepository = class {
|
|
|
444
460
|
for (const [seq, assetId] of assetIds.entries()) await this.db.update(downloadAssets).set({ seq }).where(and(eq(downloadAssets.orgId, orgId), eq(downloadAssets.downloadId, downloadId), eq(downloadAssets.assetId, assetId)));
|
|
445
461
|
return this.listDownloadAssets(orgId, downloadId);
|
|
446
462
|
}
|
|
463
|
+
async listEvents(orgId, query, ids) {
|
|
464
|
+
if (ids?.length === 0) return {
|
|
465
|
+
rows: [],
|
|
466
|
+
total: 0,
|
|
467
|
+
page: query.page,
|
|
468
|
+
pageSize: query.pageSize
|
|
469
|
+
};
|
|
470
|
+
const conditions = [eq(events.orgId, orgId)];
|
|
471
|
+
if (ids) conditions.push(inArray(events.id, ids));
|
|
472
|
+
if (query.status) conditions.push(eq(events.status, query.status));
|
|
473
|
+
if (query.from) conditions.push(gt(events.endsAt, query.from));
|
|
474
|
+
if (query.to) conditions.push(lt(events.startsAt, query.to));
|
|
475
|
+
const search = query.search?.trim();
|
|
476
|
+
if (search) conditions.push(ilike(events.title, `%${search}%`));
|
|
477
|
+
const where = and(...conditions);
|
|
478
|
+
const sort = query.sort ?? "startsAt";
|
|
479
|
+
const isDesc = sort.startsWith("-");
|
|
480
|
+
const sortExpr = eventSortColumns[isDesc ? sort.slice(1) : sort] ?? events.startsAt;
|
|
481
|
+
const direction = isDesc ? desc : asc;
|
|
482
|
+
const rows = await this.db.select({
|
|
483
|
+
event: events,
|
|
484
|
+
settingsValue: settings.value
|
|
485
|
+
}).from(events).leftJoin(settings, eventSettingsJoin).where(where).orderBy(direction(sortExpr), direction(events.id)).limit(query.pageSize).offset((query.page - 1) * query.pageSize);
|
|
486
|
+
const [totalRow] = await this.db.select({ value: count() }).from(events).where(where);
|
|
487
|
+
return {
|
|
488
|
+
rows: rows.map((row) => toEvent(row.event, row.settingsValue)),
|
|
489
|
+
total: totalRow?.value ?? 0,
|
|
490
|
+
page: query.page,
|
|
491
|
+
pageSize: query.pageSize
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
async findEventById(orgId, id) {
|
|
495
|
+
const [row] = await this.db.select({
|
|
496
|
+
event: events,
|
|
497
|
+
settingsValue: settings.value
|
|
498
|
+
}).from(events).leftJoin(settings, eventSettingsJoin).where(and(eq(events.orgId, orgId), eq(events.id, id))).limit(1);
|
|
499
|
+
return row ? toEvent(row.event, row.settingsValue) : null;
|
|
500
|
+
}
|
|
501
|
+
async findEventsByIds(orgId, ids) {
|
|
502
|
+
return (await this.db.select({
|
|
503
|
+
event: events,
|
|
504
|
+
settingsValue: settings.value
|
|
505
|
+
}).from(events).leftJoin(settings, eventSettingsJoin).where(and(eq(events.orgId, orgId), inArray(events.id, ids)))).map((row) => toEvent(row.event, row.settingsValue));
|
|
506
|
+
}
|
|
507
|
+
async createEvent(orgId, input) {
|
|
508
|
+
const id = genId("contentEvent");
|
|
509
|
+
await this.db.insert(contentItems).values({
|
|
510
|
+
orgId,
|
|
511
|
+
id,
|
|
512
|
+
type: "event"
|
|
513
|
+
});
|
|
514
|
+
await this.db.insert(events).values({
|
|
515
|
+
orgId,
|
|
516
|
+
id,
|
|
517
|
+
title: input.title,
|
|
518
|
+
description: input.description ?? "",
|
|
519
|
+
startsAt: input.startsAt,
|
|
520
|
+
endsAt: input.endsAt,
|
|
521
|
+
timeZone: input.timeZone,
|
|
522
|
+
...input.location && { location: input.location }
|
|
523
|
+
});
|
|
524
|
+
const created = await this.findEventById(orgId, id);
|
|
525
|
+
if (!created) throw new Error("failed to load created event");
|
|
526
|
+
return created;
|
|
527
|
+
}
|
|
528
|
+
async updateEvent(orgId, id, patch) {
|
|
529
|
+
const set = { updatedAt: /* @__PURE__ */ new Date() };
|
|
530
|
+
for (const key of [
|
|
531
|
+
"title",
|
|
532
|
+
"description",
|
|
533
|
+
"startsAt",
|
|
534
|
+
"endsAt",
|
|
535
|
+
"timeZone",
|
|
536
|
+
"location",
|
|
537
|
+
"thumbnailAssetId",
|
|
538
|
+
"recording",
|
|
539
|
+
"status"
|
|
540
|
+
]) if (patch[key] !== void 0) set[key] = patch[key];
|
|
541
|
+
const [updated] = await this.db.update(events).set(set).where(and(eq(events.orgId, orgId), eq(events.id, id))).returning({ id: events.id });
|
|
542
|
+
if (!updated) return null;
|
|
543
|
+
return this.findEventById(orgId, id);
|
|
544
|
+
}
|
|
545
|
+
async patchEventSettings(orgId, id, value) {
|
|
546
|
+
const merged = await this.patchSettings(orgId, id, value);
|
|
547
|
+
return {
|
|
548
|
+
...eventSettingsDefaults,
|
|
549
|
+
...merged
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
async deleteEvent(orgId, id) {
|
|
553
|
+
return (await this.db.delete(contentItems).where(and(eq(contentItems.orgId, orgId), eq(contentItems.id, id), eq(contentItems.type, "event"))).returning({ id: contentItems.id })).length > 0;
|
|
554
|
+
}
|
|
555
|
+
async deleteEventSettings(orgId, id) {
|
|
556
|
+
await this.db.delete(settings).where(and(eq(settings.orgId, orgId), eq(settings.namespace, SETTINGS_NAMESPACE), eq(settings.scopeId, id)));
|
|
557
|
+
}
|
|
558
|
+
async listEventAssets(orgId, eventId) {
|
|
559
|
+
return this.db.select().from(eventAssets).where(and(eq(eventAssets.orgId, orgId), eq(eventAssets.eventId, eventId))).orderBy(asc(eventAssets.seq));
|
|
560
|
+
}
|
|
561
|
+
async listEventAssetsFor(orgId, eventIds) {
|
|
562
|
+
return this.db.select().from(eventAssets).where(and(eq(eventAssets.orgId, orgId), inArray(eventAssets.eventId, eventIds))).orderBy(asc(eventAssets.eventId), asc(eventAssets.seq));
|
|
563
|
+
}
|
|
564
|
+
async assertEvent(orgId, eventId) {
|
|
565
|
+
const [row] = await this.db.select({ id: events.id }).from(events).where(and(eq(events.orgId, orgId), eq(events.id, eventId))).limit(1);
|
|
566
|
+
if (!row) throw new NotFoundError("Event", eventId);
|
|
567
|
+
}
|
|
568
|
+
async addEventAsset(orgId, eventId, input) {
|
|
569
|
+
await this.assertEvent(orgId, eventId);
|
|
570
|
+
const [maxRow] = await this.db.select({ maxSeq: sql`max(${eventAssets.seq})` }).from(eventAssets).where(and(eq(eventAssets.orgId, orgId), eq(eventAssets.eventId, eventId)));
|
|
571
|
+
const nextSeq = (maxRow?.maxSeq ?? -1) + 1;
|
|
572
|
+
try {
|
|
573
|
+
await this.db.insert(eventAssets).values({
|
|
574
|
+
orgId,
|
|
575
|
+
eventId,
|
|
576
|
+
assetId: input.assetId,
|
|
577
|
+
seq: nextSeq,
|
|
578
|
+
displayName: input.displayName ?? null
|
|
579
|
+
});
|
|
580
|
+
} catch (err) {
|
|
581
|
+
if (isUniqueViolation(err)) throw new ConflictError("This asset is already linked to the event");
|
|
582
|
+
throw err;
|
|
583
|
+
}
|
|
584
|
+
return this.listEventAssets(orgId, eventId);
|
|
585
|
+
}
|
|
586
|
+
async removeEventAsset(orgId, eventId, assetId) {
|
|
587
|
+
await this.assertEvent(orgId, eventId);
|
|
588
|
+
await this.db.delete(eventAssets).where(and(eq(eventAssets.orgId, orgId), eq(eventAssets.eventId, eventId), eq(eventAssets.assetId, assetId)));
|
|
589
|
+
return this.listEventAssets(orgId, eventId);
|
|
590
|
+
}
|
|
591
|
+
async renameEventAsset(orgId, eventId, assetId, displayName) {
|
|
592
|
+
await this.assertEvent(orgId, eventId);
|
|
593
|
+
await this.db.update(eventAssets).set({ displayName }).where(and(eq(eventAssets.orgId, orgId), eq(eventAssets.eventId, eventId), eq(eventAssets.assetId, assetId)));
|
|
594
|
+
return this.listEventAssets(orgId, eventId);
|
|
595
|
+
}
|
|
596
|
+
async reorderEventAssets(orgId, eventId, assetIds) {
|
|
597
|
+
await this.assertEvent(orgId, eventId);
|
|
598
|
+
for (const [seq, assetId] of assetIds.entries()) await this.db.update(eventAssets).set({ seq }).where(and(eq(eventAssets.orgId, orgId), eq(eventAssets.eventId, eventId), eq(eventAssets.assetId, assetId)));
|
|
599
|
+
return this.listEventAssets(orgId, eventId);
|
|
600
|
+
}
|
|
447
601
|
async listBundles(orgId, query) {
|
|
448
602
|
const conditions = [eq(bundles.orgId, orgId)];
|
|
449
603
|
const search = query.search?.trim();
|
|
@@ -536,8 +690,15 @@ var DrizzleContentRepository = class {
|
|
|
536
690
|
await this.db.delete(bundleItems).where(and(eq(bundleItems.orgId, orgId), eq(bundleItems.bundleId, bundleId), eq(bundleItems.contentId, contentId)));
|
|
537
691
|
return this.listBundleItems(orgId, bundleId);
|
|
538
692
|
}
|
|
539
|
-
async listCommunities(orgId, query) {
|
|
693
|
+
async listCommunities(orgId, query, ids) {
|
|
694
|
+
if (ids?.length === 0) return {
|
|
695
|
+
rows: [],
|
|
696
|
+
total: 0,
|
|
697
|
+
page: query.page,
|
|
698
|
+
pageSize: query.pageSize
|
|
699
|
+
};
|
|
540
700
|
const conditions = [eq(communities.orgId, orgId)];
|
|
701
|
+
if (ids) conditions.push(inArray(communities.id, ids));
|
|
541
702
|
if (query.status) conditions.push(eq(communities.status, query.status));
|
|
542
703
|
const search = query.search?.trim();
|
|
543
704
|
if (search) {
|
|
@@ -583,9 +744,6 @@ var DrizzleContentRepository = class {
|
|
|
583
744
|
settingsValue: settings.value
|
|
584
745
|
}).from(communities).leftJoin(settings, communitySettingsJoin).where(and(eq(communities.orgId, orgId), inArray(communities.id, ids))).orderBy(asc(communities.title), asc(communities.id))).map((row) => toCommunity(row.community, row.settingsValue));
|
|
585
746
|
}
|
|
586
|
-
async listPublishedCommunityIds(orgId) {
|
|
587
|
-
return (await this.db.select({ id: communities.id }).from(communities).where(and(eq(communities.orgId, orgId), eq(communities.status, "published"))).orderBy(asc(communities.createdAt), asc(communities.id))).map((row) => row.id);
|
|
588
|
-
}
|
|
589
747
|
async createCommunity(orgId, input, slug) {
|
|
590
748
|
const id = genId("community");
|
|
591
749
|
await this.db.insert(contentItems).values({
|
|
@@ -615,29 +773,52 @@ var DrizzleContentRepository = class {
|
|
|
615
773
|
if (!updated) return null;
|
|
616
774
|
return this.findCommunityById(orgId, id);
|
|
617
775
|
}
|
|
618
|
-
async
|
|
776
|
+
async communitiesWithDigest() {
|
|
777
|
+
return (await this.db.select({
|
|
778
|
+
orgId: communities.orgId,
|
|
779
|
+
communityId: communities.id,
|
|
780
|
+
digest: sql`${settings.value} -> 'digest'`
|
|
781
|
+
}).from(communities).innerJoin(settings, communitySettingsJoin).where(and(eq(communities.status, "published"), sql`jsonb_typeof(${settings.value} -> 'digest') = 'object'`)).orderBy(asc(communities.orgId), asc(communities.id))).flatMap((row) => {
|
|
782
|
+
const digest = storedDigest(row.digest);
|
|
783
|
+
return digest ? [{
|
|
784
|
+
orgId: row.orgId,
|
|
785
|
+
communityId: row.communityId,
|
|
786
|
+
digest
|
|
787
|
+
}] : [];
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
async patchCommunitySettings(orgId, id, input) {
|
|
619
791
|
if (!await this.findCommunityById(orgId, id)) return null;
|
|
620
|
-
const
|
|
621
|
-
await this.
|
|
792
|
+
const { digest, ...dm } = input;
|
|
793
|
+
await this.patchSettings(orgId, id, digest === void 0 ? { dm } : {
|
|
794
|
+
dm,
|
|
795
|
+
digest
|
|
796
|
+
});
|
|
797
|
+
return this.findCommunityById(orgId, id);
|
|
798
|
+
}
|
|
799
|
+
async patchSettings(orgId, scopeId, patch) {
|
|
800
|
+
const key = and(eq(settings.orgId, orgId), eq(settings.namespace, SETTINGS_NAMESPACE), eq(settings.scopeId, scopeId));
|
|
801
|
+
const value = patch;
|
|
802
|
+
return this.tx(async (tx) => {
|
|
622
803
|
let [existing] = await tx.select().from(settings).where(key).for("update");
|
|
623
|
-
const value = { dm: patch };
|
|
624
804
|
if (!existing) {
|
|
625
805
|
const [inserted] = await tx.insert(settings).values({
|
|
626
806
|
orgId,
|
|
627
807
|
namespace: SETTINGS_NAMESPACE,
|
|
628
|
-
scopeId
|
|
808
|
+
scopeId,
|
|
629
809
|
value
|
|
630
810
|
}).onConflictDoNothing().returning();
|
|
631
|
-
if (inserted) return;
|
|
811
|
+
if (inserted) return inserted.value;
|
|
632
812
|
[existing] = await tx.select().from(settings).where(key).for("update");
|
|
633
|
-
if (!existing) throw new Error(
|
|
813
|
+
if (!existing) throw new Error(`settings patch for ${scopeId}: row vanished mid-transaction`);
|
|
634
814
|
}
|
|
635
|
-
await tx.update(settings).set({
|
|
636
|
-
value: deepMerge(existing.value,
|
|
815
|
+
const [updated] = await tx.update(settings).set({
|
|
816
|
+
value: deepMerge(existing.value, patch),
|
|
637
817
|
updatedAt: /* @__PURE__ */ new Date()
|
|
638
|
-
}).where(key);
|
|
818
|
+
}).where(key).returning();
|
|
819
|
+
if (!updated) throw new Error(`settings patch for ${scopeId} returned no row`);
|
|
820
|
+
return updated.value;
|
|
639
821
|
});
|
|
640
|
-
return this.findCommunityById(orgId, id);
|
|
641
822
|
}
|
|
642
823
|
async deleteCommunity(orgId, id) {
|
|
643
824
|
return (await this.db.delete(contentItems).where(and(eq(contentItems.orgId, orgId), eq(contentItems.id, id), eq(contentItems.type, "community"))).returning({ id: contentItems.id })).length > 0;
|
|
@@ -779,6 +960,6 @@ var DrizzleContentRepository = class {
|
|
|
779
960
|
};
|
|
780
961
|
translateDbErrors(DrizzleContentRepository);
|
|
781
962
|
//#endregion
|
|
782
|
-
export { DrizzleContentRepository };
|
|
963
|
+
export { DrizzleContentRepository, SETTINGS_NAMESPACE };
|
|
783
964
|
|
|
784
965
|
//# sourceMappingURL=content.js.map
|