Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.191
0.1.192
40 changes: 21 additions & 19 deletions packages/cockroach/src/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,11 @@ import {
type CardType,
type MessageData,
type PatchData,
type BlobMetadata,
NotificationType,
type NotificationContent
type NotificationContent,
type FileData,
type LinkPreviewData,
type LinkPreviewID
} from '@hcengineering/communication-types'
import type {
DbAdapter,
Expand Down Expand Up @@ -148,32 +150,32 @@ export class CockroachAdapter implements DbAdapter {
card: CardID,
message: MessageID,
messageCreated: Date,
blobId: BlobID,
fileType: string,
filename: string,
size: number,
meta: BlobMetadata | undefined,
data: FileData,
creator: SocialID,
created: Date
): Promise<void> {
await this.message.createFile(
card,
message,
messageCreated,
blobId,
fileType,
filename,
size,
meta,
creator,
created
)
await this.message.createFile(card, message, messageCreated, data, creator, created)
}

async removeFiles(card: CardID, query: RemoveFileQuery): Promise<void> {
await this.message.removeFiles(card, query)
}

async createLinkPreview(
card: CardID,
message: MessageID,
messageCreated: Date,
data: LinkPreviewData,
creator: SocialID,
created: Date
): Promise<LinkPreviewID> {
return await this.message.createLinkPreview(card, message, messageCreated, data, creator, created)
}

async removeLinkPreview(card: CardID, message: MessageID, id: LinkPreviewID): Promise<void> {
await this.message.removeLinkPreview(card, message, id)
}

async createThread(
card: CardID,
message: MessageID,
Expand Down
34 changes: 25 additions & 9 deletions packages/cockroach/src/db/mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ import {
type Label,
type CardType,
type BlobMetadata,
type AccountID
type AccountID,
type LinkPreview,
type LinkPreviewID
} from '@hcengineering/communication-types'
import { applyPatches } from '@hcengineering/communication-shared'

Expand All @@ -50,7 +52,8 @@ import {
type PatchDb,
type ReactionDb,
type ThreadDb,
type LabelDb
type LabelDb,
type LinkPreviewDb
} from './schema'

interface RawMessage extends MessageDb {
Expand All @@ -61,6 +64,7 @@ interface RawMessage extends MessageDb {
patches?: PatchDb[]
files?: FileDb[]
reactions?: ReactionDb[]
link_previews?: LinkPreviewDb[]
}

interface RawNotification extends NotificationDb {
Expand Down Expand Up @@ -102,7 +106,6 @@ type RawContext = ContextDb & { id: ContextID } & {

export function toMessage(raw: RawMessage): Message {
const patches = (raw.patches ?? []).map((it) => toPatch(it))

const rawMessage: Message = {
id: String(raw.id) as MessageID,
type: raw.type,
Expand All @@ -126,7 +129,8 @@ export function toMessage(raw: RawMessage): Message {
}
: undefined,
reactions: (raw.reactions ?? []).map(toReaction),
files: (raw.files ?? []).map(toFile)
files: (raw.files ?? []).map(toFile),
links: (raw.link_previews ?? []).map(toLinkPreview)
}

if (patches.length === 0) {
Expand All @@ -138,7 +142,6 @@ export function toMessage(raw: RawMessage): Message {

export function toReaction(raw: ReactionDb): Reaction {
return {
message: String(raw.message_id) as MessageID,
reaction: raw.reaction,
creator: raw.creator,
created: new Date(raw.created)
Expand All @@ -147,9 +150,6 @@ export function toReaction(raw: ReactionDb): Reaction {

export function toFile(raw: Omit<FileDb, 'workspace_id'>): File {
return {
card: raw.card_id,
message: String(raw.message_id) as MessageID,
messageCreated: new Date(raw.message_created),
blobId: raw.blob_id,
type: raw.type,
filename: raw.filename,
Expand All @@ -160,6 +160,21 @@ export function toFile(raw: Omit<FileDb, 'workspace_id'>): File {
}
}

export function toLinkPreview(raw: LinkPreviewDb): LinkPreview {
return {
id: String(raw.id) as LinkPreviewID,
url: raw.url,
host: raw.host,
title: raw.title ?? undefined,
description: raw.description ?? undefined,
favicon: raw.favicon ?? undefined,
hostname: raw.hostname ?? undefined,
image: raw.image ?? undefined,
created: new Date(raw.created),
creator: raw.creator
}
}

export function toMessagesGroup(raw: MessagesGroupDb): MessagesGroup {
return {
card: raw.card_id,
Expand Down Expand Up @@ -272,7 +287,8 @@ function toNotificationRaw(id: ContextID, card: CardID, raw: RawNotification): N
edited: undefined,
reactions: [],
files: messageFiles ?? [],
thread
thread,
links: []
}

if (patches.length > 0) {
Expand Down
133 changes: 113 additions & 20 deletions packages/cockroach/src/db/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,15 @@ import {
type SocialID,
SortingOrder,
type Thread,
type BlobMetadata
type FileData,
type LinkPreviewData,
type LinkPreviewID
} from '@hcengineering/communication-types'

import { BaseDb } from './base'
import {
type FileDb,
type LinkPreviewDb,
type MessageDb,
messageSchema,
type MessagesGroupDb,
Expand Down Expand Up @@ -146,26 +149,22 @@ export class MessagesDb extends BaseDb {
card: CardID,
message: MessageID,
messageCreated: Date,
blobId: BlobID,
fileType: string,
filename: string,
size: number,
meta: BlobMetadata | undefined,
data: FileData,
creator: SocialID,
created: Date
): Promise<void> {
const db: FileDb = {
workspace_id: this.workspace,
card_id: card,
message_id: message,
blob_id: blobId,
type: fileType,
filename,
size,
blob_id: data.blobId,
type: data.type,
filename: data.filename,
size: data.size,
creator,
created,
message_created: messageCreated,
meta
meta: data.meta
}
const sql = `INSERT INTO ${TableName.File} (workspace_id, card_id, message_id, blob_id, type, filename, creator,
created, message_created, size, meta)
Expand Down Expand Up @@ -213,6 +212,60 @@ export class MessagesDb extends BaseDb {
await this.execute(sql, whereValues, 'remove files')
}

async createLinkPreview(
card: CardID,
message: MessageID,
messageCreated: Date,
data: LinkPreviewData,
creator: SocialID,
created: Date
): Promise<LinkPreviewID> {
const db: Omit<LinkPreviewDb, 'id'> = {
workspace_id: this.workspace,
card_id: card,
message_id: message,
message_created: messageCreated,
url: data.url,
host: data.host,
title: data.title ?? null,
description: data.description ?? null,
favicon: data.favicon ?? null,
hostname: data.hostname ?? null,
image: data.image ?? null,
creator,
created
}
const sql = `INSERT INTO ${TableName.LinkPreview} (workspace_id, card_id, message_id, url, host, title, description, favicon, hostname, image, creator, created, message_created)
VALUES ($1::uuid, $2::varchar, $3::int8, $4::varchar, $5::varchar, $6::varchar, $7::varchar, $8::varchar, $9::varchar, $10::jsonb, $11::varchar, $12::timestamptz, $13::timestamptz)
RETURNING id::text`
const result = await this.execute(
sql,
[
db.workspace_id,
db.card_id,
db.message_id,
db.url,
db.host,
db.title,
db.description,
db.favicon,
db.hostname,
db.image,
db.creator,
db.created,
db.message_created
],
'insert link preview'
)

return result[0].id as LinkPreviewID
}

async removeLinkPreview(card: CardID, message: MessageID, id: LinkPreviewID): Promise<void> {
const sql = `DELETE FROM ${TableName.LinkPreview} WHERE workspace_id = $1::uuid AND card_id = $2::varchar AND message_id = $3::int8 AND id = $4::int8`
await this.execute(sql, [this.workspace, card, message, id], 'remove link preview')
}

// Reaction
async createReaction(
card: CardID,
Expand Down Expand Up @@ -411,6 +464,7 @@ export class MessagesDb extends BaseDb {
WITH
${this.buildCteLimitedMessages(where, orderBy, limit)}
${this.buildCteAggregatedFiles(params)}
${this.buildCteAggregatedLinkPreviews(params)}
${this.buildCteAggregatedReactions(params)}
${this.buildCteAggregatedPatches()}
${this.buildMainSelect(params)}
Expand Down Expand Up @@ -449,9 +503,6 @@ export class MessagesDb extends BaseDb {
f.card_id,
f.message_id,
jsonb_agg(jsonb_build_object(
'card_id', f.card_id,
'message_id', f.message_id::text,
'message_created', f.message_created,
'blob_id', f.blob_id,
'type', f.type,
'size', f.size,
Expand All @@ -470,6 +521,36 @@ export class MessagesDb extends BaseDb {
`
}

private buildCteAggregatedLinkPreviews(params: FindMessagesParams): string {
if (!params.links) return ''
return `,
agg_link_previews AS (
SELECT
l.workspace_id,
l.card_id,
l.message_id,
jsonb_agg(jsonb_build_object(
'id', l.id::text,
'url', l.url,
'host', l.host,
'title', l.title,
'description', l.description,
'favicon', l.favicon,
'hostname', l.hostname,
'image', l.image,
'creator', l.creator,
'created', l.created
)) AS link_previews
FROM ${TableName.LinkPreview} l
INNER JOIN limited_messages m
ON m.workspace_id = l.workspace_id
AND m.card_id = l.card_id
AND m.id = l.message_id
GROUP BY l.workspace_id, l.card_id, l.message_id
)
`
}

private buildCteAggregatedReactions(params: FindMessagesParams): string {
if (!params.reactions) return ''
return `,
Expand All @@ -479,7 +560,6 @@ export class MessagesDb extends BaseDb {
r.card_id,
r.message_id,
jsonb_agg(jsonb_build_object(
'message_id', r.message_id::text,
'reaction', r.reaction,
'creator', r.creator,
'created', r.created
Expand Down Expand Up @@ -526,6 +606,9 @@ export class MessagesDb extends BaseDb {
: ''

const selectFiles = params.files ? `COALESCE(f.files, '[]'::jsonb) AS files,` : `'[]'::jsonb AS files,`
const selectLinks = params.links
? `COALESCE(l.link_previews, '[]'::jsonb) AS link_previews,`
: `'[]'::jsonb AS link_previews,`

const selectReactions = params.reactions
? `COALESCE(r.reactions, '[]'::jsonb) AS reactions,`
Expand All @@ -539,6 +622,14 @@ export class MessagesDb extends BaseDb {
AND f.message_id = m.id`
: ''

const joinLinks = params.links
? `
LEFT JOIN agg_link_previews l
ON l.workspace_id = m.workspace_id
AND l.card_id = m.card_id
AND l.message_id = m.id`
: ''

const joinReactions = params.reactions
? `
LEFT JOIN agg_reactions r
Expand All @@ -557,16 +648,18 @@ export class MessagesDb extends BaseDb {
m.data,
m.external_id,
${selectReplies}
${selectFiles}
${selectReactions}
COALESCE(p.patches, '[]'::jsonb) AS patches
${selectFiles}
${selectLinks}
${selectReactions}
COALESCE(p.patches, '[]'::jsonb) AS patches
FROM limited_messages m
LEFT JOIN ${TableName.Thread} t
ON t.workspace_id = m.workspace_id
AND t.card_id = m.card_id
AND t.message_id = m.id
${joinFiles}
${joinReactions}
${joinFiles}
${joinLinks}
${joinReactions}
LEFT JOIN agg_patches p
ON p.workspace_id = m.workspace_id
AND p.card_id = m.card_id
Expand Down
Loading