@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
|
@@ -4,15 +4,15 @@ import { orgUsers } from "../schema/organizations.js";
|
|
|
4
4
|
import { contentAccess, spaceMembers } from "../schema/entitlements.js";
|
|
5
5
|
import "../schema/index.js";
|
|
6
6
|
import { translateDbErrors } from "./pg-errors.js";
|
|
7
|
-
import { communityMember, communityPublished } from "./grant-covers.js";
|
|
8
|
-
import {
|
|
7
|
+
import { communityMember, communityPublished, oneOf } from "./grant-covers.js";
|
|
8
|
+
import { directEventGrantIds, eventAttendeePage, eventFacesFor, memberEventIds } from "./event-reports.js";
|
|
9
9
|
import { noopLogger } from "@headless-lms/core/shared/logger";
|
|
10
|
+
import { and, asc, eq, ilike, inArray, sql } from "drizzle-orm";
|
|
10
11
|
//#region src/repositories/member.ts
|
|
11
12
|
function personColumns(orgId) {
|
|
12
13
|
return {
|
|
13
14
|
orgUserId: orgUsers.id,
|
|
14
15
|
userId: orgUsers.userId,
|
|
15
|
-
role: orgUsers.role,
|
|
16
16
|
displayName: sql`coalesce(nullif(trim(${userProfiles.displayName}), ''), nullif(trim(concat_ws(' ', ${users.firstName}, ${users.lastName})), ''))`,
|
|
17
17
|
headline: userProfiles.headline,
|
|
18
18
|
bio: userProfiles.bio,
|
|
@@ -26,10 +26,10 @@ var DrizzleMemberRepository = class {
|
|
|
26
26
|
this.db = db;
|
|
27
27
|
this.logger = logger;
|
|
28
28
|
}
|
|
29
|
-
async directory(orgId, communityId, query) {
|
|
29
|
+
async directory(orgId, communityId, query, readerIds) {
|
|
30
30
|
const columns = personColumns(orgId);
|
|
31
31
|
const q = query.search?.trim();
|
|
32
|
-
const where = and(eq(orgUsers.orgId, orgId), communityMember(sql`${orgUsers.orgId}`, sql`${orgUsers.id}`, sql`${
|
|
32
|
+
const where = and(eq(orgUsers.orgId, orgId), communityMember(sql`${orgUsers.orgId}`, sql`${orgUsers.id}`, sql`${communityId}`, readerIds), q ? ilike(columns.displayName, `%${q}%`) : void 0);
|
|
33
33
|
const rows = await this.db.select(columns).from(orgUsers).leftJoin(userProfiles, eq(userProfiles.userId, orgUsers.userId)).leftJoin(users, eq(users.id, orgUsers.userId)).where(where).orderBy(asc(userProfiles.displayName), asc(orgUsers.id)).limit(query.pageSize).offset((query.page - 1) * query.pageSize);
|
|
34
34
|
const [{ total } = { total: 0 }] = await this.db.select({ total: sql`cast(count(*) as int)` }).from(orgUsers).leftJoin(userProfiles, eq(userProfiles.userId, orgUsers.userId)).leftJoin(users, eq(users.id, orgUsers.userId)).where(where);
|
|
35
35
|
return {
|
|
@@ -43,12 +43,24 @@ var DrizzleMemberRepository = class {
|
|
|
43
43
|
if (orgUserIds.length === 0) return [];
|
|
44
44
|
return this.db.select(personColumns(orgId)).from(orgUsers).leftJoin(userProfiles, eq(userProfiles.userId, orgUsers.userId)).leftJoin(users, eq(users.id, orgUsers.userId)).where(and(eq(orgUsers.orgId, orgId), inArray(orgUsers.id, orgUserIds)));
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
eventAttendees(orgId, eventId, page) {
|
|
47
|
+
return eventAttendeePage(this.db, orgId, eventId, page);
|
|
48
|
+
}
|
|
49
|
+
eventFaces(orgId, eventIds, limit) {
|
|
50
|
+
return eventFacesFor(this.db, orgId, eventIds, limit);
|
|
51
|
+
}
|
|
52
|
+
directEventGrants(orgId, orgUserId, eventIds) {
|
|
53
|
+
return directEventGrantIds(this.db, orgId, orgUserId, eventIds);
|
|
54
|
+
}
|
|
55
|
+
events(orgId, query, reader, now) {
|
|
56
|
+
return memberEventIds(this.db, orgId, query, reader, now);
|
|
57
|
+
}
|
|
58
|
+
async spaceMemberCounts(orgId, communityId, excluding) {
|
|
47
59
|
const holders = this.db.$with("holders").as(this.db.selectDistinct({ orgUserId: contentAccess.orgUserId }).from(contentAccess).where(and(eq(contentAccess.orgId, orgId), eq(contentAccess.contentId, communityId), communityPublished(sql`${orgId}`, sql`${communityId}`))));
|
|
48
60
|
const seated = this.db.$with("seated").as(this.db.select({
|
|
49
61
|
spaceId: spaceMembers.spaceId,
|
|
50
62
|
count: sql`cast(count(*) as int)`.as("count")
|
|
51
|
-
}).from(spaceMembers).innerJoin(holders, eq(holders.orgUserId, spaceMembers.orgUserId)).where(and(eq(spaceMembers.orgId, orgId), eq(spaceMembers.communityId, communityId), eq(spaceMembers.status, "active"))).groupBy(spaceMembers.spaceId));
|
|
63
|
+
}).from(spaceMembers).innerJoin(holders, eq(holders.orgUserId, spaceMembers.orgUserId)).where(and(eq(spaceMembers.orgId, orgId), eq(spaceMembers.communityId, communityId), eq(spaceMembers.status, "active"), excluding.length > 0 ? sql`not ${oneOf(sql`${spaceMembers.orgUserId}`, excluding)}` : void 0)).groupBy(spaceMembers.spaceId));
|
|
52
64
|
const rows = await this.db.with(holders, seated).select({
|
|
53
65
|
spaceId: spaces.id,
|
|
54
66
|
count: sql`case when ${spaces.accessRule} = 'all_members' then (select cast(count(*) as int) from ${holders}) else coalesce(${sql.identifier("seated")}.${sql.identifier("count")}, 0) end`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"member.js","names":[],"sources":["../../src/repositories/member.ts"],"sourcesContent":["// member — Drizzle read repo (implements the reporting/member outbound port).\nimport { and, asc, eq, ilike, inArray, sql } from \"drizzle-orm\";\nimport type { NodePgDatabase } from \"drizzle-orm/node-postgres\";\nimport type {\n DirectoryQuery,\n DirectoryRow,\n MemberReportRepository,\n} from \"@headless-lms/core/reporting/member\";\nimport type { Page } from \"@headless-lms/core/types\";\nimport {\n contentAccess,\n orgUsers,\n spaceMembers,\n spaces,\n userProfiles,\n users,\n} from \"../schema/index.js\";\nimport type { Logger } from \"@headless-lms/core/shared/ports\";\nimport { noopLogger } from \"@headless-lms/core/shared/logger\";\nimport { translateDbErrors } from \"./pg-errors.js\";\nimport { communityMember, communityPublished } from \"./grant-covers.js\";\n\nfunction personColumns(orgId: string) {\n return {\n orgUserId: orgUsers.id,\n userId: orgUsers.userId,\n
|
|
1
|
+
{"version":3,"file":"member.js","names":[],"sources":["../../src/repositories/member.ts"],"sourcesContent":["// member — Drizzle read repo (implements the reporting/member outbound port).\nimport { and, asc, eq, ilike, inArray, sql } from \"drizzle-orm\";\nimport type { NodePgDatabase } from \"drizzle-orm/node-postgres\";\nimport type {\n DirectoryQuery,\n DirectoryRow,\n EventAttendeeRow,\n EventReader,\n MemberReportRepository,\n} from \"@headless-lms/core/reporting/member\";\nimport type { MemberEventsQuery, Page } from \"@headless-lms/core/types\";\nimport type { EventFaces } from \"@headless-lms/core/reporting/events\";\nimport {\n contentAccess,\n orgUsers,\n spaceMembers,\n spaces,\n userProfiles,\n users,\n} from \"../schema/index.js\";\nimport type { Logger } from \"@headless-lms/core/shared/ports\";\nimport { noopLogger } from \"@headless-lms/core/shared/logger\";\nimport { translateDbErrors } from \"./pg-errors.js\";\nimport { communityMember, communityPublished, oneOf } from \"./grant-covers.js\";\nimport {\n directEventGrantIds,\n eventAttendeePage,\n eventFacesFor,\n memberEventIds,\n} from \"./event-reports.js\";\n\nfunction personColumns(orgId: string) {\n return {\n orgUserId: orgUsers.id,\n userId: orgUsers.userId,\n displayName: sql<\n string | null\n >`coalesce(nullif(trim(${userProfiles.displayName}), ''), nullif(trim(concat_ws(' ', ${users.firstName}, ${users.lastName})), ''))`,\n headline: userProfiles.headline,\n bio: userProfiles.bio,\n imageAssetId: sql<\n string | null\n >`case when ${userProfiles.imageAssetOrgId} = ${orgId} then ${userProfiles.imageAssetId} end`,\n };\n}\n\nexport class DrizzleMemberRepository implements MemberReportRepository {\n constructor(\n private readonly db: NodePgDatabase,\n private readonly logger: Logger = noopLogger,\n ) {}\n\n async directory(\n orgId: string,\n communityId: string,\n query: DirectoryQuery,\n readerIds: string[],\n ): Promise<Page<DirectoryRow>> {\n const columns = personColumns(orgId);\n const q = query.search?.trim();\n const where = and(\n eq(orgUsers.orgId, orgId),\n communityMember(sql`${orgUsers.orgId}`, sql`${orgUsers.id}`, sql`${communityId}`, readerIds),\n q ? ilike(columns.displayName, `%${q}%`) : undefined,\n );\n const rows = await this.db\n .select(columns)\n .from(orgUsers)\n .leftJoin(userProfiles, eq(userProfiles.userId, orgUsers.userId))\n .leftJoin(users, eq(users.id, orgUsers.userId))\n .where(where)\n .orderBy(asc(userProfiles.displayName), asc(orgUsers.id))\n .limit(query.pageSize)\n .offset((query.page - 1) * query.pageSize);\n const [{ total } = { total: 0 }] = await this.db\n .select({ total: sql<number>`cast(count(*) as int)` })\n .from(orgUsers)\n .leftJoin(userProfiles, eq(userProfiles.userId, orgUsers.userId))\n .leftJoin(users, eq(users.id, orgUsers.userId))\n .where(where);\n return { rows, total, page: query.page, pageSize: query.pageSize };\n }\n\n async people(orgId: string, orgUserIds: string[]): Promise<DirectoryRow[]> {\n if (orgUserIds.length === 0) {\n return [];\n }\n return this.db\n .select(personColumns(orgId))\n .from(orgUsers)\n .leftJoin(userProfiles, eq(userProfiles.userId, orgUsers.userId))\n .leftJoin(users, eq(users.id, orgUsers.userId))\n .where(and(eq(orgUsers.orgId, orgId), inArray(orgUsers.id, orgUserIds)));\n }\n\n eventAttendees(\n orgId: string,\n eventId: string,\n page: { page: number; pageSize: number },\n ): Promise<Page<EventAttendeeRow>> {\n return eventAttendeePage(this.db, orgId, eventId, page);\n }\n\n eventFaces(\n orgId: string,\n eventIds: string[],\n limit: number,\n ): Promise<Record<string, EventFaces>> {\n return eventFacesFor(this.db, orgId, eventIds, limit);\n }\n\n directEventGrants(orgId: string, orgUserId: string, eventIds: string[]): Promise<string[]> {\n return directEventGrantIds(this.db, orgId, orgUserId, eventIds);\n }\n\n events(\n orgId: string,\n query: MemberEventsQuery,\n reader: EventReader,\n now: Date,\n ): Promise<Page<string>> {\n return memberEventIds(this.db, orgId, query, reader, now);\n }\n\n async spaceMemberCounts(\n orgId: string,\n communityId: string,\n excluding: string[],\n ): Promise<Record<string, number>> {\n const holders = this.db.$with(\"holders\").as(\n this.db\n .selectDistinct({ orgUserId: contentAccess.orgUserId })\n .from(contentAccess)\n .where(\n and(\n eq(contentAccess.orgId, orgId),\n eq(contentAccess.contentId, communityId),\n communityPublished(sql`${orgId}`, sql`${communityId}`),\n ),\n ),\n );\n const seated = this.db.$with(\"seated\").as(\n this.db\n .select({\n spaceId: spaceMembers.spaceId,\n count: sql<number>`cast(count(*) as int)`.as(\"count\"),\n })\n .from(spaceMembers)\n .innerJoin(holders, eq(holders.orgUserId, spaceMembers.orgUserId))\n .where(\n and(\n eq(spaceMembers.orgId, orgId),\n eq(spaceMembers.communityId, communityId),\n eq(spaceMembers.status, \"active\"),\n excluding.length > 0\n ? sql`not ${oneOf(sql`${spaceMembers.orgUserId}`, excluding)}`\n : undefined,\n ),\n )\n .groupBy(spaceMembers.spaceId),\n );\n const rows = await this.db\n .with(holders, seated)\n .select({\n spaceId: spaces.id,\n count: sql<number>`case when ${spaces.accessRule} = 'all_members' then (select cast(count(*) as int) from ${holders}) else coalesce(${sql.identifier(\"seated\")}.${sql.identifier(\"count\")}, 0) end`,\n })\n .from(spaces)\n .leftJoin(seated, eq(seated.spaceId, spaces.id))\n .where(and(eq(spaces.orgId, orgId), eq(spaces.communityId, communityId)));\n return Object.fromEntries(rows.map((row) => [row.spaceId, Number(row.count)]));\n }\n}\ntranslateDbErrors(DrizzleMemberRepository);\n"],"mappings":"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"}
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
2
|
-
import {
|
|
2
|
+
import { MembersRepository, TeamRow } from "@headless-lms/core/organizations";
|
|
3
3
|
import { Logger } from "@headless-lms/core/shared/ports";
|
|
4
4
|
//#region src/repositories/members.d.ts
|
|
5
5
|
declare class DrizzleMembersRepository implements MembersRepository {
|
|
6
6
|
private readonly db;
|
|
7
7
|
private readonly logger;
|
|
8
8
|
constructor(db: NodePgDatabase, logger?: Logger);
|
|
9
|
-
|
|
10
|
-
list(orgId: string, query: MembersQuery): Promise<Page<Member>>;
|
|
11
|
-
findByEmail(orgId: string, email: string): Promise<MemberRecord | null>;
|
|
12
|
-
findById(orgId: string, id: string): Promise<MemberRecord | null>;
|
|
9
|
+
teamRows(orgId: string, memberRoleKey: string): Promise<TeamRow[]>;
|
|
13
10
|
}
|
|
14
11
|
//#endregion
|
|
15
12
|
export { DrizzleMembersRepository };
|
|
@@ -1,26 +1,12 @@
|
|
|
1
1
|
import { users } from "../schema/identity.js";
|
|
2
2
|
import { invites, orgUsers } from "../schema/organizations.js";
|
|
3
|
+
import { roleAssignments } from "../schema/roles.js";
|
|
3
4
|
import { translateDbErrors } from "./pg-errors.js";
|
|
4
5
|
import { user } from "../schema/better-auth.js";
|
|
5
6
|
import { orgUserProfileColumns } from "./org-user-profile.js";
|
|
6
|
-
import { and, eq, ne } from "drizzle-orm";
|
|
7
7
|
import { noopLogger } from "@headless-lms/core/shared/logger";
|
|
8
|
-
import {
|
|
8
|
+
import { and, eq, inArray, isNotNull, or, sql } from "drizzle-orm";
|
|
9
9
|
//#region src/repositories/members.ts
|
|
10
|
-
const roleOf = (t) => isRole(t) && t !== STUDENT_ROLE ? t : "instructor";
|
|
11
|
-
function toMember(r) {
|
|
12
|
-
return {
|
|
13
|
-
id: r.id,
|
|
14
|
-
firstName: r.firstName,
|
|
15
|
-
lastName: r.lastName,
|
|
16
|
-
email: r.email,
|
|
17
|
-
image: r.image,
|
|
18
|
-
role: r.role,
|
|
19
|
-
status: r.status,
|
|
20
|
-
joinedAt: r.joinedAt,
|
|
21
|
-
invitedAt: r.invitedAt
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
10
|
var DrizzleMembersRepository = class {
|
|
25
11
|
db;
|
|
26
12
|
logger;
|
|
@@ -28,87 +14,46 @@ var DrizzleMembersRepository = class {
|
|
|
28
14
|
this.db = db;
|
|
29
15
|
this.logger = logger;
|
|
30
16
|
}
|
|
31
|
-
async
|
|
32
|
-
const
|
|
33
|
-
...orgUserProfileColumns,
|
|
34
|
-
role: orgUsers.role,
|
|
35
|
-
joinedAt: orgUsers.createdAt,
|
|
36
|
-
userExternalId: users.externalId
|
|
37
|
-
}).from(orgUsers).innerJoin(users, eq(users.id, orgUsers.userId)).leftJoin(user, eq(user.id, users.externalId)).where(and(eq(orgUsers.orgId, orgId), ne(orgUsers.role, STUDENT_ROLE)));
|
|
38
|
-
const inviteRows = await this.db.select({
|
|
39
|
-
id: invites.id,
|
|
17
|
+
async teamRows(orgId, memberRoleKey) {
|
|
18
|
+
const pendingInvite = this.db.select({
|
|
40
19
|
email: invites.email,
|
|
41
|
-
|
|
20
|
+
roleKey: invites.roleKey,
|
|
42
21
|
invitedAt: invites.createdAt
|
|
43
|
-
}).from(invites).where(and(eq(invites.orgId, orgId), eq(invites.status, "pending")
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}));
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (query.status) rows = rows.filter((r) => r.status === query.status);
|
|
78
|
-
const q = query.search?.trim().toLowerCase();
|
|
79
|
-
if (q) rows = rows.filter((r) => [
|
|
80
|
-
r.firstName,
|
|
81
|
-
r.lastName,
|
|
82
|
-
r.email
|
|
83
|
-
].some((v) => v?.toLowerCase().includes(q)));
|
|
84
|
-
const sort = query.sort;
|
|
85
|
-
const desc = sort?.startsWith("-") ?? false;
|
|
86
|
-
const key = desc ? sort.slice(1) : sort;
|
|
87
|
-
const byName = (a, b) => a === b ? 0 : a === null ? 1 : b === null ? -1 : a.localeCompare(b);
|
|
88
|
-
rows.sort((a, b) => {
|
|
89
|
-
if (key === "email") return desc ? -a.email.localeCompare(b.email) : a.email.localeCompare(b.email);
|
|
90
|
-
if (key === "role") return desc ? -a.role.localeCompare(b.role) : a.role.localeCompare(b.role);
|
|
91
|
-
if (key === "lastName") {
|
|
92
|
-
const cmp = byName(a.lastName, b.lastName) || byName(a.firstName, b.firstName);
|
|
93
|
-
return desc ? -cmp : cmp;
|
|
94
|
-
}
|
|
95
|
-
const cmp = byName(a.firstName, b.firstName) || byName(a.lastName, b.lastName);
|
|
96
|
-
return desc ? -cmp : cmp;
|
|
22
|
+
}).from(invites).where(and(eq(invites.orgId, orgId), eq(invites.status, "pending"))).as("pending_invite");
|
|
23
|
+
const rows = await this.db.select({
|
|
24
|
+
...orgUserProfileColumns,
|
|
25
|
+
status: orgUsers.status,
|
|
26
|
+
joinedAt: orgUsers.createdAt,
|
|
27
|
+
inviteRoleKey: pendingInvite.roleKey,
|
|
28
|
+
invitedAt: pendingInvite.invitedAt
|
|
29
|
+
}).from(orgUsers).innerJoin(users, eq(users.id, orgUsers.userId)).leftJoin(user, eq(user.id, users.externalId)).leftJoin(pendingInvite, sql`lower(${pendingInvite.email}) = lower(${users.email})`).where(and(eq(orgUsers.orgId, orgId), or(sql`exists (select 1 from ${roleAssignments} ra where ra.org_id = ${orgUsers.orgId} and ra.org_user_id = ${orgUsers.id})`, and(eq(orgUsers.status, "invited"), isNotNull(pendingInvite.roleKey), sql`${pendingInvite.roleKey} <> ${memberRoleKey}`))));
|
|
30
|
+
if (rows.length === 0) return [];
|
|
31
|
+
const assignments = await this.db.select({
|
|
32
|
+
orgUserId: roleAssignments.orgUserId,
|
|
33
|
+
roleKey: roleAssignments.roleKey,
|
|
34
|
+
contentId: roleAssignments.contentId,
|
|
35
|
+
contentType: roleAssignments.contentType
|
|
36
|
+
}).from(roleAssignments).where(and(eq(roleAssignments.orgId, orgId), inArray(roleAssignments.orgUserId, rows.map((row) => row.id))));
|
|
37
|
+
return rows.map((row) => {
|
|
38
|
+
const own = assignments.filter((a) => a.orgUserId === row.id);
|
|
39
|
+
return {
|
|
40
|
+
id: row.id,
|
|
41
|
+
firstName: row.firstName,
|
|
42
|
+
lastName: row.lastName,
|
|
43
|
+
email: row.email,
|
|
44
|
+
image: row.image ?? null,
|
|
45
|
+
status: row.status,
|
|
46
|
+
joinedAt: row.joinedAt,
|
|
47
|
+
invitedAt: row.invitedAt ?? null,
|
|
48
|
+
orgRoleKey: own.find((a) => a.contentId === null)?.roleKey ?? null,
|
|
49
|
+
inviteRoleKey: row.inviteRoleKey ?? null,
|
|
50
|
+
items: own.filter((a) => a.contentId !== null && a.contentType !== null).map((a) => ({
|
|
51
|
+
contentId: a.contentId,
|
|
52
|
+
contentType: a.contentType,
|
|
53
|
+
roleKey: a.roleKey
|
|
54
|
+
}))
|
|
55
|
+
};
|
|
97
56
|
});
|
|
98
|
-
const total = rows.length;
|
|
99
|
-
const start = (query.page - 1) * query.pageSize;
|
|
100
|
-
return {
|
|
101
|
-
rows: rows.slice(start, start + query.pageSize).map(toMember),
|
|
102
|
-
total,
|
|
103
|
-
page: query.page,
|
|
104
|
-
pageSize: query.pageSize
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
async findByEmail(orgId, email) {
|
|
108
|
-
return (await this.loadAll(orgId)).find((r) => r.email.toLowerCase() === email.toLowerCase()) ?? null;
|
|
109
|
-
}
|
|
110
|
-
async findById(orgId, id) {
|
|
111
|
-
return (await this.loadAll(orgId)).find((r) => r.id === id) ?? null;
|
|
112
57
|
}
|
|
113
58
|
};
|
|
114
59
|
translateDbErrors(DrizzleMembersRepository);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"members.js","names":[],"sources":["../../src/repositories/members.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"members.js","names":[],"sources":["../../src/repositories/members.ts"],"sourcesContent":["import { and, eq, inArray, isNotNull, or, sql } from \"drizzle-orm\";\nimport type { NodePgDatabase } from \"drizzle-orm/node-postgres\";\nimport type { MembersRepository, TeamRow } from \"@headless-lms/core/organizations\";\nimport type { ContentType } from \"@headless-lms/core/types\";\nimport { orgUsers, invites } from \"../schema/organizations.js\";\nimport { roleAssignments } from \"../schema/roles.js\";\nimport { users } from \"../schema/identity.js\";\nimport { user } from \"../schema/better-auth.js\";\nimport type { Logger } from \"@headless-lms/core/shared/ports\";\nimport { noopLogger } from \"@headless-lms/core/shared/logger\";\nimport { orgUserProfileColumns } from \"./org-user-profile.js\";\nimport { translateDbErrors } from \"./pg-errors.js\";\n\nexport class DrizzleMembersRepository implements MembersRepository {\n constructor(\n private readonly db: NodePgDatabase,\n private readonly logger: Logger = noopLogger,\n ) {}\n\n async teamRows(orgId: string, memberRoleKey: string): Promise<TeamRow[]> {\n const pendingInvite = this.db\n .select({\n email: invites.email,\n roleKey: invites.roleKey,\n invitedAt: invites.createdAt,\n })\n .from(invites)\n .where(and(eq(invites.orgId, orgId), eq(invites.status, \"pending\")))\n .as(\"pending_invite\");\n const rows = await this.db\n .select({\n ...orgUserProfileColumns,\n status: orgUsers.status,\n joinedAt: orgUsers.createdAt,\n inviteRoleKey: pendingInvite.roleKey,\n invitedAt: pendingInvite.invitedAt,\n })\n .from(orgUsers)\n .innerJoin(users, eq(users.id, orgUsers.userId))\n .leftJoin(user, eq(user.id, users.externalId))\n .leftJoin(pendingInvite, sql`lower(${pendingInvite.email}) = lower(${users.email})`)\n .where(\n and(\n eq(orgUsers.orgId, orgId),\n or(\n sql`exists (select 1 from ${roleAssignments} ra where ra.org_id = ${orgUsers.orgId} and ra.org_user_id = ${orgUsers.id})`,\n and(\n eq(orgUsers.status, \"invited\"),\n isNotNull(pendingInvite.roleKey),\n sql`${pendingInvite.roleKey} <> ${memberRoleKey}`,\n ),\n ),\n ),\n );\n if (rows.length === 0) {\n return [];\n }\n const assignments = await this.db\n .select({\n orgUserId: roleAssignments.orgUserId,\n roleKey: roleAssignments.roleKey,\n contentId: roleAssignments.contentId,\n contentType: roleAssignments.contentType,\n })\n .from(roleAssignments)\n .where(\n and(\n eq(roleAssignments.orgId, orgId),\n inArray(\n roleAssignments.orgUserId,\n rows.map((row) => row.id),\n ),\n ),\n );\n return rows.map((row) => {\n const own = assignments.filter((a) => a.orgUserId === row.id);\n return {\n id: row.id,\n firstName: row.firstName,\n lastName: row.lastName,\n email: row.email,\n image: row.image ?? null,\n status: row.status,\n joinedAt: row.joinedAt,\n invitedAt: row.invitedAt ?? null,\n orgRoleKey: own.find((a) => a.contentId === null)?.roleKey ?? null,\n inviteRoleKey: row.inviteRoleKey ?? null,\n items: own\n .filter((a) => a.contentId !== null && a.contentType !== null)\n .map((a) => ({\n contentId: a.contentId!,\n contentType: a.contentType as ContentType,\n roleKey: a.roleKey,\n })),\n };\n });\n }\n}\ntranslateDbErrors(DrizzleMembersRepository);\n"],"mappings":";;;;;;;;;AAaA,IAAa,2BAAb,MAAmE;CAE9C;CACA;CAFnB,YACE,IACA,SAAkC,YAClC;EAFiB,KAAA,KAAA;EACA,KAAA,SAAA;CAChB;CAEH,MAAM,SAAS,OAAe,eAA2C;EACvE,MAAM,gBAAgB,KAAK,GACxB,OAAO;GACN,OAAO,QAAQ;GACf,SAAS,QAAQ;GACjB,WAAW,QAAQ;EACrB,CAAC,CAAC,CACD,KAAK,OAAO,CAAC,CACb,MAAM,IAAI,GAAG,QAAQ,OAAO,KAAK,GAAG,GAAG,QAAQ,QAAQ,SAAS,CAAC,CAAC,CAAC,CACnE,GAAG,gBAAgB;EACtB,MAAM,OAAO,MAAM,KAAK,GACrB,OAAO;GACN,GAAG;GACH,QAAQ,SAAS;GACjB,UAAU,SAAS;GACnB,eAAe,cAAc;GAC7B,WAAW,cAAc;EAC3B,CAAC,CAAC,CACD,KAAK,QAAQ,CAAC,CACd,UAAU,OAAO,GAAG,MAAM,IAAI,SAAS,MAAM,CAAC,CAAC,CAC/C,SAAS,MAAM,GAAG,KAAK,IAAI,MAAM,UAAU,CAAC,CAAC,CAC7C,SAAS,eAAe,GAAG,SAAS,cAAc,MAAM,YAAY,MAAM,MAAM,EAAE,CAAC,CACnF,MACC,IACE,GAAG,SAAS,OAAO,KAAK,GACxB,GACE,GAAG,yBAAyB,gBAAgB,wBAAwB,SAAS,MAAM,wBAAwB,SAAS,GAAG,IACvH,IACE,GAAG,SAAS,QAAQ,SAAS,GAC7B,UAAU,cAAc,OAAO,GAC/B,GAAG,GAAG,cAAc,QAAQ,MAAM,eACpC,CACF,CACF,CACF;EACF,IAAI,KAAK,WAAW,GAClB,OAAO,CAAC;EAEV,MAAM,cAAc,MAAM,KAAK,GAC5B,OAAO;GACN,WAAW,gBAAgB;GAC3B,SAAS,gBAAgB;GACzB,WAAW,gBAAgB;GAC3B,aAAa,gBAAgB;EAC/B,CAAC,CAAC,CACD,KAAK,eAAe,CAAC,CACrB,MACC,IACE,GAAG,gBAAgB,OAAO,KAAK,GAC/B,QACE,gBAAgB,WAChB,KAAK,KAAK,QAAQ,IAAI,EAAE,CAC1B,CACF,CACF;EACF,OAAO,KAAK,KAAK,QAAQ;GACvB,MAAM,MAAM,YAAY,QAAQ,MAAM,EAAE,cAAc,IAAI,EAAE;GAC5D,OAAO;IACL,IAAI,IAAI;IACR,WAAW,IAAI;IACf,UAAU,IAAI;IACd,OAAO,IAAI;IACX,OAAO,IAAI,SAAS;IACpB,QAAQ,IAAI;IACZ,UAAU,IAAI;IACd,WAAW,IAAI,aAAa;IAC5B,YAAY,IAAI,MAAM,MAAM,EAAE,cAAc,IAAI,CAAC,EAAE,WAAW;IAC9D,eAAe,IAAI,iBAAiB;IACpC,OAAO,IACJ,QAAQ,MAAM,EAAE,cAAc,QAAQ,EAAE,gBAAgB,IAAI,CAAC,CAC7D,KAAK,OAAO;KACX,WAAW,EAAE;KACb,aAAa,EAAE;KACf,SAAS,EAAE;IACb,EAAE;GACN;EACF,CAAC;CACH;AACF;AACA,kBAAkB,wBAAwB"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
2
|
+
import { Logger, MentionItemType } from "@headless-lms/core/types";
|
|
3
|
+
import { MentionsRepository } from "@headless-lms/core/discussion";
|
|
4
|
+
//#region src/repositories/mentions.d.ts
|
|
5
|
+
declare class DrizzleMentionsRepository implements MentionsRepository {
|
|
6
|
+
private readonly db;
|
|
7
|
+
private readonly logger;
|
|
8
|
+
constructor(db: NodePgDatabase, logger?: Logger);
|
|
9
|
+
ofItem(orgId: string, itemType: MentionItemType, itemId: string): Promise<string[]>;
|
|
10
|
+
forItems(orgId: string, itemType: MentionItemType, itemIds: string[]): Promise<Record<string, string[]>>;
|
|
11
|
+
sync(orgId: string, itemType: MentionItemType, itemId: string, orgUserIds: string[], at: Date): Promise<string[]>;
|
|
12
|
+
removeItem(orgId: string, itemType: MentionItemType, itemId: string): Promise<void>;
|
|
13
|
+
private item;
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { DrizzleMentionsRepository };
|
|
17
|
+
//# sourceMappingURL=mentions.d.ts.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { mentions } from "../schema/discussion.js";
|
|
2
|
+
import "../schema/index.js";
|
|
3
|
+
import { noopLogger } from "@headless-lms/core/shared/logger";
|
|
4
|
+
import { and, asc, eq, inArray, notInArray } from "drizzle-orm";
|
|
5
|
+
//#region src/repositories/mentions.ts
|
|
6
|
+
var DrizzleMentionsRepository = class {
|
|
7
|
+
db;
|
|
8
|
+
logger;
|
|
9
|
+
constructor(db, logger = noopLogger) {
|
|
10
|
+
this.db = db;
|
|
11
|
+
this.logger = logger;
|
|
12
|
+
}
|
|
13
|
+
async ofItem(orgId, itemType, itemId) {
|
|
14
|
+
return (await this.db.select({ orgUserId: mentions.orgUserId }).from(mentions).where(this.item(orgId, itemType, itemId)).orderBy(asc(mentions.createdAt), asc(mentions.orgUserId))).map((row) => row.orgUserId);
|
|
15
|
+
}
|
|
16
|
+
async forItems(orgId, itemType, itemIds) {
|
|
17
|
+
if (itemIds.length === 0) return {};
|
|
18
|
+
const rows = await this.db.select({
|
|
19
|
+
itemId: mentions.itemId,
|
|
20
|
+
orgUserId: mentions.orgUserId
|
|
21
|
+
}).from(mentions).where(and(eq(mentions.orgId, orgId), eq(mentions.itemType, itemType), inArray(mentions.itemId, itemIds))).orderBy(asc(mentions.itemId), asc(mentions.createdAt), asc(mentions.orgUserId));
|
|
22
|
+
const byItem = {};
|
|
23
|
+
for (const row of rows) (byItem[row.itemId] ??= []).push(row.orgUserId);
|
|
24
|
+
return byItem;
|
|
25
|
+
}
|
|
26
|
+
async sync(orgId, itemType, itemId, orgUserIds, at) {
|
|
27
|
+
const item = this.item(orgId, itemType, itemId);
|
|
28
|
+
await this.db.delete(mentions).where(orgUserIds.length > 0 ? and(item, notInArray(mentions.orgUserId, orgUserIds)) : item);
|
|
29
|
+
if (orgUserIds.length === 0) return [];
|
|
30
|
+
const added = await this.db.insert(mentions).values(orgUserIds.map((orgUserId) => ({
|
|
31
|
+
orgId,
|
|
32
|
+
itemType,
|
|
33
|
+
itemId,
|
|
34
|
+
orgUserId,
|
|
35
|
+
createdAt: at
|
|
36
|
+
}))).onConflictDoNothing().returning({ orgUserId: mentions.orgUserId });
|
|
37
|
+
this.logger.debug("mentions synced", {
|
|
38
|
+
orgId,
|
|
39
|
+
itemType,
|
|
40
|
+
itemId,
|
|
41
|
+
added: added.length
|
|
42
|
+
});
|
|
43
|
+
return added.map((row) => row.orgUserId);
|
|
44
|
+
}
|
|
45
|
+
async removeItem(orgId, itemType, itemId) {
|
|
46
|
+
await this.db.delete(mentions).where(this.item(orgId, itemType, itemId));
|
|
47
|
+
}
|
|
48
|
+
item(orgId, itemType, itemId) {
|
|
49
|
+
return and(eq(mentions.orgId, orgId), eq(mentions.itemType, itemType), eq(mentions.itemId, itemId));
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
//#endregion
|
|
53
|
+
export { DrizzleMentionsRepository };
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=mentions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mentions.js","names":[],"sources":["../../src/repositories/mentions.ts"],"sourcesContent":["import { and, asc, eq, inArray, notInArray } from \"drizzle-orm\";\nimport type { NodePgDatabase } from \"drizzle-orm/node-postgres\";\nimport type { MentionsRepository } from \"@headless-lms/core/discussion\";\nimport type { Logger, MentionItemType } from \"@headless-lms/core/types\";\nimport { noopLogger } from \"@headless-lms/core/shared/logger\";\nimport { mentions } from \"../schema/index.js\";\n\nexport class DrizzleMentionsRepository implements MentionsRepository {\n constructor(\n private readonly db: NodePgDatabase,\n private readonly logger: Logger = noopLogger,\n ) {}\n\n async ofItem(orgId: string, itemType: MentionItemType, itemId: string): Promise<string[]> {\n const rows = await this.db\n .select({ orgUserId: mentions.orgUserId })\n .from(mentions)\n .where(this.item(orgId, itemType, itemId))\n .orderBy(asc(mentions.createdAt), asc(mentions.orgUserId));\n return rows.map((row) => row.orgUserId);\n }\n\n async forItems(\n orgId: string,\n itemType: MentionItemType,\n itemIds: string[],\n ): Promise<Record<string, string[]>> {\n if (itemIds.length === 0) {\n return {};\n }\n const rows = await this.db\n .select({ itemId: mentions.itemId, orgUserId: mentions.orgUserId })\n .from(mentions)\n .where(\n and(\n eq(mentions.orgId, orgId),\n eq(mentions.itemType, itemType),\n inArray(mentions.itemId, itemIds),\n ),\n )\n .orderBy(asc(mentions.itemId), asc(mentions.createdAt), asc(mentions.orgUserId));\n const byItem: Record<string, string[]> = {};\n for (const row of rows) {\n (byItem[row.itemId] ??= []).push(row.orgUserId);\n }\n return byItem;\n }\n\n async sync(\n orgId: string,\n itemType: MentionItemType,\n itemId: string,\n orgUserIds: string[],\n at: Date,\n ): Promise<string[]> {\n const item = this.item(orgId, itemType, itemId);\n await this.db\n .delete(mentions)\n .where(orgUserIds.length > 0 ? and(item, notInArray(mentions.orgUserId, orgUserIds)) : item);\n if (orgUserIds.length === 0) {\n return [];\n }\n const added = await this.db\n .insert(mentions)\n .values(\n orgUserIds.map((orgUserId) => ({ orgId, itemType, itemId, orgUserId, createdAt: at })),\n )\n .onConflictDoNothing()\n .returning({ orgUserId: mentions.orgUserId });\n this.logger.debug(\"mentions synced\", { orgId, itemType, itemId, added: added.length });\n return added.map((row) => row.orgUserId);\n }\n\n async removeItem(orgId: string, itemType: MentionItemType, itemId: string): Promise<void> {\n await this.db.delete(mentions).where(this.item(orgId, itemType, itemId));\n }\n\n private item(orgId: string, itemType: MentionItemType, itemId: string) {\n return and(\n eq(mentions.orgId, orgId),\n eq(mentions.itemType, itemType),\n eq(mentions.itemId, itemId),\n );\n }\n}\n"],"mappings":";;;;;AAOA,IAAa,4BAAb,MAAqE;CAEhD;CACA;CAFnB,YACE,IACA,SAAkC,YAClC;EAFiB,KAAA,KAAA;EACA,KAAA,SAAA;CAChB;CAEH,MAAM,OAAO,OAAe,UAA2B,QAAmC;EAMxF,QAAO,MALY,KAAK,GACrB,OAAO,EAAE,WAAW,SAAS,UAAU,CAAC,CAAC,CACzC,KAAK,QAAQ,CAAC,CACd,MAAM,KAAK,KAAK,OAAO,UAAU,MAAM,CAAC,CAAC,CACzC,QAAQ,IAAI,SAAS,SAAS,GAAG,IAAI,SAAS,SAAS,CAAC,EAAA,CAC/C,KAAK,QAAQ,IAAI,SAAS;CACxC;CAEA,MAAM,SACJ,OACA,UACA,SACmC;EACnC,IAAI,QAAQ,WAAW,GACrB,OAAO,CAAC;EAEV,MAAM,OAAO,MAAM,KAAK,GACrB,OAAO;GAAE,QAAQ,SAAS;GAAQ,WAAW,SAAS;EAAU,CAAC,CAAC,CAClE,KAAK,QAAQ,CAAC,CACd,MACC,IACE,GAAG,SAAS,OAAO,KAAK,GACxB,GAAG,SAAS,UAAU,QAAQ,GAC9B,QAAQ,SAAS,QAAQ,OAAO,CAClC,CACF,CAAC,CACA,QAAQ,IAAI,SAAS,MAAM,GAAG,IAAI,SAAS,SAAS,GAAG,IAAI,SAAS,SAAS,CAAC;EACjF,MAAM,SAAmC,CAAC;EAC1C,KAAK,MAAM,OAAO,MAChB,CAAC,OAAO,IAAI,YAAY,CAAC,EAAA,CAAG,KAAK,IAAI,SAAS;EAEhD,OAAO;CACT;CAEA,MAAM,KACJ,OACA,UACA,QACA,YACA,IACmB;EACnB,MAAM,OAAO,KAAK,KAAK,OAAO,UAAU,MAAM;EAC9C,MAAM,KAAK,GACR,OAAO,QAAQ,CAAC,CAChB,MAAM,WAAW,SAAS,IAAI,IAAI,MAAM,WAAW,SAAS,WAAW,UAAU,CAAC,IAAI,IAAI;EAC7F,IAAI,WAAW,WAAW,GACxB,OAAO,CAAC;EAEV,MAAM,QAAQ,MAAM,KAAK,GACtB,OAAO,QAAQ,CAAC,CAChB,OACC,WAAW,KAAK,eAAe;GAAE;GAAO;GAAU;GAAQ;GAAW,WAAW;EAAG,EAAE,CACvF,CAAC,CACA,oBAAoB,CAAC,CACrB,UAAU,EAAE,WAAW,SAAS,UAAU,CAAC;EAC9C,KAAK,OAAO,MAAM,mBAAmB;GAAE;GAAO;GAAU;GAAQ,OAAO,MAAM;EAAO,CAAC;EACrF,OAAO,MAAM,KAAK,QAAQ,IAAI,SAAS;CACzC;CAEA,MAAM,WAAW,OAAe,UAA2B,QAA+B;EACxF,MAAM,KAAK,GAAG,OAAO,QAAQ,CAAC,CAAC,MAAM,KAAK,KAAK,OAAO,UAAU,MAAM,CAAC;CACzE;CAEA,KAAa,OAAe,UAA2B,QAAgB;EACrE,OAAO,IACL,GAAG,SAAS,OAAO,KAAK,GACxB,GAAG,SAAS,UAAU,QAAQ,GAC9B,GAAG,SAAS,QAAQ,MAAM,CAC5B;CACF;AACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
2
|
+
import { Logger, StoredSetting } from "@headless-lms/core/types";
|
|
3
|
+
import { NotificationSettingsRepository, SettingKey } from "@headless-lms/core/identity";
|
|
4
|
+
//#region src/repositories/notification-settings.d.ts
|
|
5
|
+
declare class DrizzleNotificationSettingsRepository implements NotificationSettingsRepository {
|
|
6
|
+
private readonly db;
|
|
7
|
+
private readonly logger;
|
|
8
|
+
constructor(db: NodePgDatabase, logger?: Logger);
|
|
9
|
+
forUsers(orgId: string, userIds: string[], communityId: string | null, categories: string[] | null): Promise<(StoredSetting & {
|
|
10
|
+
userId: string;
|
|
11
|
+
})[]>;
|
|
12
|
+
apply(orgId: string, userId: string, upserts: (SettingKey & {
|
|
13
|
+
enabled: boolean;
|
|
14
|
+
})[], deletes: SettingKey[], at: Date): Promise<void>;
|
|
15
|
+
switchedOn(orgId: string, communityId: string, category: string, spaceId: string | null): Promise<string[]>;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { DrizzleNotificationSettingsRepository };
|
|
19
|
+
//# sourceMappingURL=notification-settings.d.ts.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { notificationSettings } from "../schema/identity.js";
|
|
2
|
+
import { orgUsers } from "../schema/organizations.js";
|
|
3
|
+
import "../schema/index.js";
|
|
4
|
+
import { translateDbErrors } from "./pg-errors.js";
|
|
5
|
+
import { noopLogger } from "@headless-lms/core/shared/logger";
|
|
6
|
+
import { and, eq, inArray, sql } from "drizzle-orm";
|
|
7
|
+
import { genId } from "@headless-lms/core/shared/id";
|
|
8
|
+
//#region src/repositories/notification-settings.ts
|
|
9
|
+
const ns = notificationSettings;
|
|
10
|
+
const communityKey = sql`coalesce(${ns.communityId}, '')`;
|
|
11
|
+
const spaceKey = sql`coalesce(${ns.spaceId}, '')`;
|
|
12
|
+
function matchesKey(key) {
|
|
13
|
+
return sql`(${communityKey} = ${key.communityId ?? ""} and ${spaceKey} = ${key.spaceId ?? ""} and ${ns.category} = ${key.category} and ${ns.channel} = ${key.channel})`;
|
|
14
|
+
}
|
|
15
|
+
var DrizzleNotificationSettingsRepository = class {
|
|
16
|
+
db;
|
|
17
|
+
logger;
|
|
18
|
+
constructor(db, logger = noopLogger) {
|
|
19
|
+
this.db = db;
|
|
20
|
+
this.logger = logger;
|
|
21
|
+
}
|
|
22
|
+
async forUsers(orgId, userIds, communityId, categories) {
|
|
23
|
+
if (userIds.length === 0) return [];
|
|
24
|
+
const conditions = [
|
|
25
|
+
eq(ns.orgId, orgId),
|
|
26
|
+
inArray(ns.userId, userIds),
|
|
27
|
+
sql`${communityKey} = ${communityId ?? ""}`
|
|
28
|
+
];
|
|
29
|
+
if (categories !== null) {
|
|
30
|
+
if (categories.length === 0) return [];
|
|
31
|
+
conditions.push(inArray(ns.category, categories));
|
|
32
|
+
}
|
|
33
|
+
return this.db.select({
|
|
34
|
+
userId: ns.userId,
|
|
35
|
+
communityId: ns.communityId,
|
|
36
|
+
spaceId: ns.spaceId,
|
|
37
|
+
category: ns.category,
|
|
38
|
+
channel: ns.channel,
|
|
39
|
+
enabled: ns.enabled
|
|
40
|
+
}).from(ns).where(and(...conditions));
|
|
41
|
+
}
|
|
42
|
+
async apply(orgId, userId, upserts, deletes, at) {
|
|
43
|
+
if (upserts.length === 0 && deletes.length === 0) return;
|
|
44
|
+
await this.db.transaction(async (tx) => {
|
|
45
|
+
if (deletes.length > 0) await tx.delete(ns).where(and(eq(ns.orgId, orgId), eq(ns.userId, userId), sql`(${sql.join(deletes.map(matchesKey), sql` or `)})`));
|
|
46
|
+
if (upserts.length > 0) {
|
|
47
|
+
const rows = upserts.map((row) => sql`(${orgId}, ${genId("notificationSetting")}, ${userId}, ${row.communityId}, ${row.spaceId}, ${row.category}, ${row.channel}, ${row.enabled}, ${at.toISOString()}::timestamptz)`);
|
|
48
|
+
await tx.execute(sql`insert into notification_settings (org_id, id, user_id, community_id, space_id, category, channel, enabled, updated_at) values ${sql.join(rows, sql`, `)} on conflict (org_id, user_id, coalesce(community_id, ''), coalesce(space_id, ''), category, channel) do update set enabled = excluded.enabled, updated_at = excluded.updated_at`);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
this.logger.debug("notification settings applied", {
|
|
52
|
+
orgId,
|
|
53
|
+
userId,
|
|
54
|
+
upserts: upserts.length,
|
|
55
|
+
deletes: deletes.length
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
async switchedOn(orgId, communityId, category, spaceId) {
|
|
59
|
+
const levels = spaceId === null ? [""] : [spaceId, ""];
|
|
60
|
+
return (await this.db.selectDistinct({ orgUserId: orgUsers.id }).from(ns).innerJoin(orgUsers, and(eq(orgUsers.orgId, ns.orgId), eq(orgUsers.userId, ns.userId))).where(and(eq(ns.orgId, orgId), sql`${communityKey} = ${communityId}`, eq(ns.category, category), sql`${spaceKey} in (${sql.join(levels.map((level) => sql`${level}`), sql`, `)})`, sql`${ns.enabled}`))).map((row) => row.orgUserId);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
translateDbErrors(DrizzleNotificationSettingsRepository);
|
|
64
|
+
//#endregion
|
|
65
|
+
export { DrizzleNotificationSettingsRepository };
|
|
66
|
+
|
|
67
|
+
//# sourceMappingURL=notification-settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-settings.js","names":[],"sources":["../../src/repositories/notification-settings.ts"],"sourcesContent":["import { and, eq, inArray, sql, type SQL } from \"drizzle-orm\";\nimport type { NodePgDatabase } from \"drizzle-orm/node-postgres\";\nimport type { NotificationSettingsRepository, SettingKey } from \"@headless-lms/core/identity\";\nimport type { Logger, StoredSetting } from \"@headless-lms/core/types\";\nimport { genId } from \"@headless-lms/core/shared/id\";\nimport { noopLogger } from \"@headless-lms/core/shared/logger\";\nimport { notificationSettings, orgUsers } from \"../schema/index.js\";\nimport { translateDbErrors } from \"./pg-errors.js\";\n\nconst ns = notificationSettings;\nconst communityKey = sql`coalesce(${ns.communityId}, '')`;\nconst spaceKey = sql`coalesce(${ns.spaceId}, '')`;\n\nfunction matchesKey(key: SettingKey): SQL {\n return sql`(${communityKey} = ${key.communityId ?? \"\"} and ${spaceKey} = ${key.spaceId ?? \"\"} and ${ns.category} = ${key.category} and ${ns.channel} = ${key.channel})`;\n}\n\nexport class DrizzleNotificationSettingsRepository implements NotificationSettingsRepository {\n constructor(\n private readonly db: NodePgDatabase,\n private readonly logger: Logger = noopLogger,\n ) {}\n\n async forUsers(\n orgId: string,\n userIds: string[],\n communityId: string | null,\n categories: string[] | null,\n ): Promise<(StoredSetting & { userId: string })[]> {\n if (userIds.length === 0) {\n return [];\n }\n const conditions = [\n eq(ns.orgId, orgId),\n inArray(ns.userId, userIds),\n sql`${communityKey} = ${communityId ?? \"\"}`,\n ];\n if (categories !== null) {\n if (categories.length === 0) {\n return [];\n }\n conditions.push(inArray(ns.category, categories));\n }\n return this.db\n .select({\n userId: ns.userId,\n communityId: ns.communityId,\n spaceId: ns.spaceId,\n category: ns.category,\n channel: ns.channel,\n enabled: ns.enabled,\n })\n .from(ns)\n .where(and(...conditions));\n }\n\n async apply(\n orgId: string,\n userId: string,\n upserts: (SettingKey & { enabled: boolean })[],\n deletes: SettingKey[],\n at: Date,\n ): Promise<void> {\n if (upserts.length === 0 && deletes.length === 0) {\n return;\n }\n await this.db.transaction(async (tx) => {\n if (deletes.length > 0) {\n await tx\n .delete(ns)\n .where(\n and(\n eq(ns.orgId, orgId),\n eq(ns.userId, userId),\n sql`(${sql.join(deletes.map(matchesKey), sql` or `)})`,\n ),\n );\n }\n if (upserts.length > 0) {\n const rows = upserts.map(\n (row) =>\n sql`(${orgId}, ${genId(\"notificationSetting\")}, ${userId}, ${row.communityId}, ${row.spaceId}, ${row.category}, ${row.channel}, ${row.enabled}, ${at.toISOString()}::timestamptz)`,\n );\n await tx.execute(\n sql`insert into notification_settings (org_id, id, user_id, community_id, space_id, category, channel, enabled, updated_at) values ${sql.join(rows, sql`, `)} on conflict (org_id, user_id, coalesce(community_id, ''), coalesce(space_id, ''), category, channel) do update set enabled = excluded.enabled, updated_at = excluded.updated_at`,\n );\n }\n });\n this.logger.debug(\"notification settings applied\", {\n orgId,\n userId,\n upserts: upserts.length,\n deletes: deletes.length,\n });\n }\n\n async switchedOn(\n orgId: string,\n communityId: string,\n category: string,\n spaceId: string | null,\n ): Promise<string[]> {\n const levels = spaceId === null ? [\"\"] : [spaceId, \"\"];\n const rows = await this.db\n .selectDistinct({ orgUserId: orgUsers.id })\n .from(ns)\n .innerJoin(orgUsers, and(eq(orgUsers.orgId, ns.orgId), eq(orgUsers.userId, ns.userId)))\n .where(\n and(\n eq(ns.orgId, orgId),\n sql`${communityKey} = ${communityId}`,\n eq(ns.category, category),\n sql`${spaceKey} in (${sql.join(\n levels.map((level) => sql`${level}`),\n sql`, `,\n )})`,\n sql`${ns.enabled}`,\n ),\n );\n return rows.map((row) => row.orgUserId);\n }\n}\ntranslateDbErrors(DrizzleNotificationSettingsRepository);\n"],"mappings":"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"}
|
|
@@ -1,22 +1,29 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { DbExecutor } from "../client.js";
|
|
2
|
+
import { Delivery, NotificationFilter, StoredNotification } from "@headless-lms/core/types";
|
|
3
|
+
import { ListedNotification, NewDelivery, NewNotification, NotificationPage, NotificationsRepository, UnreadCounts } from "@headless-lms/core/automations";
|
|
4
4
|
//#region src/repositories/notifications.d.ts
|
|
5
5
|
declare class DrizzleNotificationsRepository implements NotificationsRepository {
|
|
6
6
|
private readonly db;
|
|
7
|
-
constructor(db:
|
|
8
|
-
insert(orgId: string, rows:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
7
|
+
constructor(db: DbExecutor);
|
|
8
|
+
insert(orgId: string, rows: NewNotification[], deliveries: NewDelivery[]): Promise<void>;
|
|
9
|
+
pendingDeliveriesForEvent(orgId: string, sourceEventId: string): Promise<{
|
|
10
|
+
id: string;
|
|
11
|
+
}[]>;
|
|
12
|
+
findDelivery(orgId: string, deliveryId: string): Promise<{
|
|
13
|
+
delivery: Delivery;
|
|
14
|
+
notification: StoredNotification;
|
|
15
|
+
} | null>;
|
|
16
|
+
markSent(orgId: string, deliveryId: string, at: Date): Promise<void>;
|
|
17
|
+
recordError(orgId: string, deliveryId: string, error: string): Promise<void>;
|
|
18
|
+
markFailed(orgId: string, deliveryId: string, error: string): Promise<void>;
|
|
19
|
+
page(orgId: string, userId: string, filter: NotificationFilter, page: {
|
|
20
|
+
page: number;
|
|
21
|
+
pageSize: number;
|
|
22
|
+
}): Promise<NotificationPage>;
|
|
23
|
+
find(orgId: string, userId: string, notificationId: string): Promise<ListedNotification | null>;
|
|
24
|
+
unreadCounts(orgId: string, userId: string, communityIds: string[]): Promise<UnreadCounts>;
|
|
25
|
+
markRead(orgId: string, userId: string, notificationId: string, at: Date): Promise<boolean>;
|
|
26
|
+
markAllRead(orgId: string, userId: string, filter: NotificationFilter, at: Date): Promise<number>;
|
|
20
27
|
}
|
|
21
28
|
//#endregion
|
|
22
29
|
export { DrizzleNotificationsRepository };
|