This commit is contained in:
Philipinho
2025-08-14 08:58:23 -07:00
parent 5012a68d85
commit ace00a0b0a
43 changed files with 2552 additions and 103 deletions
File diff suppressed because it is too large Load Diff
@@ -22,24 +22,6 @@ export class PageRepo {
private spaceMemberRepo: SpaceMemberRepo,
) {}
withHasChildren(eb: ExpressionBuilder<DB, 'pages'>) {
return eb
.selectFrom('pages as child')
.select((eb) =>
eb
.case()
.when(eb.fn.countAll(), '>', 0)
.then(true)
.else(false)
.end()
.as('count'),
)
.whereRef('child.parentPageId', '=', 'pages.id')
.where('child.deletedAt', 'is', null)
.limit(1)
.as('hasChildren');
}
private baseFields: Array<keyof Page> = [
'id',
'slugId',
@@ -379,6 +361,24 @@ export class PageRepo {
).as('contributors');
}
withHasChildren(eb: ExpressionBuilder<DB, 'pages'>) {
return eb
.selectFrom('pages as child')
.select((eb) =>
eb
.case()
.when(eb.fn.countAll(), '>', 0)
.then(true)
.else(false)
.end()
.as('count'),
)
.whereRef('child.parentPageId', '=', 'pages.id')
.where('child.deletedAt', 'is', null)
.limit(1)
.as('hasChildren');
}
async getPageAndDescendants(
parentPageId: string,
opts: { includeContent: boolean },
@@ -420,4 +420,46 @@ export class PageRepo {
.selectAll()
.execute();
}
async update(
pageId: string,
updatablePage: UpdatablePage,
trx?: KyselyTransaction,
): Promise<void> {
const db = dbOrTx(this.db, trx);
await db
.updateTable('pages')
.set({ ...updatablePage, updatedAt: new Date() })
.where('id', '=', pageId)
.execute();
}
async getAllDescendants(
pageId: string,
trx?: KyselyTransaction,
): Promise<string[]> {
const db = dbOrTx(this.db, trx);
// Recursive CTE to get all descendants
const descendants = await db
.withRecursive('page_tree', (qb) =>
qb
.selectFrom('pages')
.select(['id', 'parentPageId'])
.where('parentPageId', '=', pageId)
.where('deletedAt', 'is', null)
.unionAll((eb) =>
eb
.selectFrom('pages as p')
.innerJoin('page_tree as pt', 'p.parentPageId', 'pt.id')
.select(['p.id', 'p.parentPageId'])
.where('p.deletedAt', 'is', null),
),
)
.selectFrom('page_tree')
.select('id')
.execute();
return descendants.map((d) => d.id);
}
}
@@ -0,0 +1,58 @@
import { Injectable } from '@nestjs/common';
import { InjectKysely } from 'nestjs-kysely';
import { KyselyDB } from '../../types/kysely.types';
import { Page } from '../../types/entity.types';
import { PageMemberRole } from './page-permission-repo.service';
@Injectable()
export class SharedPagesRepo {
constructor(@InjectKysely() private readonly db: KyselyDB) {}
async addSharedPage(userId: string, pageId: string): Promise<void> {
await this.db
.insertInto('userSharedPages')
.values({
userId,
pageId,
sharedAt: new Date(),
})
.onConflict((oc) => oc.columns(['userId', 'pageId']).doNothing())
.execute();
}
async removeSharedPage(userId: string, pageId: string): Promise<void> {
await this.db
.deleteFrom('userSharedPages')
.where('userId', '=', userId)
.where('pageId', '=', pageId)
.execute();
}
async getUserSharedPages(userId: string): Promise<Page[]> {
return await this.db
.selectFrom('userSharedPages as usp')
.innerJoin('pages as p', 'p.id', 'usp.pageId')
.innerJoin('pagePermissions as pm', (join) =>
join
.onRef('pm.pageId', '=', 'p.id')
.on('pm.userId', '=', userId)
.on('pm.role', '!=', PageMemberRole.NONE),
)
.selectAll('p')
.where('usp.userId', '=', userId)
.where('p.deletedAt', 'is', null)
.orderBy('usp.sharedAt', 'desc')
.execute();
}
async isPageSharedWithUser(userId: string, pageId: string): Promise<boolean> {
const result = await this.db
.selectFrom('userSharedPages')
.select('userId')
.where('userId', '=', userId)
.where('pageId', '=', pageId)
.executeTakeFirst();
return !!result;
}
}